From dcbf7ef6de0eedc346d668392a639026340226e7 Mon Sep 17 00:00:00 2001 From: wangxiaodong1030 Date: Tue, 21 Jan 2025 11:27:45 +0800 Subject: [PATCH] code update 2025_01_21 --- README.md | 10 +- docs/ChangeLog.md | 58 + drivers/eth/gmac/fgmac_os.c | 4 +- drivers/eth/xmac/fxmac_os.c | 1 + drivers/media/fmedia_os.c | 19 +- drivers/media/fmedia_os.h | 2 +- .../d2000_aarch32_test_eventgroup.config | 7 + .../d2000_aarch64_test_eventgroup.config | 7 + .../e2000d_aarch32_demo_eventgroup.config | 7 + .../e2000d_aarch64_demo_eventgroup.config | 7 + .../e2000q_aarch32_demo_eventgroup.config | 7 + .../e2000q_aarch64_demo_eventgroup.config | 7 + .../ft2004_aarch32_dsk_eventgroup.config | 7 + .../ft2004_aarch64_dsk_eventgroup.config | 7 + ...hytiumpi_aarch32_firefly_eventgroup.config | 7 + ...hytiumpi_aarch64_firefly_eventgroup.config | 7 + example/freertos_feature/eventgroup/sdkconfig | 7 + .../freertos_feature/eventgroup/sdkconfig.h | 7 + .../d2000_aarch32_test_interrupt.config | 7 + .../d2000_aarch64_test_interrupt.config | 7 + .../e2000d_aarch32_demo_interrupt.config | 7 + .../e2000d_aarch64_demo_interrupt.config | 7 + .../e2000q_aarch32_demo_interrupt.config | 7 + .../e2000q_aarch64_demo_interrupt.config | 7 + .../ft2004_aarch32_dsk_interrupt.config | 7 + .../ft2004_aarch64_dsk_interrupt.config | 7 + ...phytiumpi_aarch32_firefly_interrupt.config | 7 + ...phytiumpi_aarch64_firefly_interrupt.config | 7 + example/freertos_feature/interrupt/sdkconfig | 7 + .../freertos_feature/interrupt/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_queue.config | 7 + .../configs/d2000_aarch64_test_queue.config | 7 + .../configs/e2000d_aarch32_demo_queue.config | 7 + .../configs/e2000d_aarch64_demo_queue.config | 7 + .../configs/e2000q_aarch32_demo_queue.config | 7 + .../configs/e2000q_aarch64_demo_queue.config | 7 + .../configs/ft2004_aarch32_dsk_queue.config | 7 + .../configs/ft2004_aarch64_dsk_queue.config | 7 + .../phytiumpi_aarch32_firefly_queue.config | 7 + .../phytiumpi_aarch64_firefly_queue.config | 7 + example/freertos_feature/queue/sdkconfig | 7 + example/freertos_feature/queue/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_resoure.config | 7 + .../configs/d2000_aarch64_test_resoure.config | 7 + .../e2000d_aarch32_demo_resoure.config | 7 + .../e2000d_aarch64_demo_resoure.config | 7 + .../e2000q_aarch32_demo_resoure.config | 7 + .../e2000q_aarch64_demo_resoure.config | 7 + .../configs/ft2004_aarch32_dsk_resoure.config | 7 + .../configs/ft2004_aarch64_dsk_resoure.config | 7 + .../phytiumpi_aarch32_firefly_resoure.config | 7 + .../phytiumpi_aarch64_firefly_resoure.config | 7 + example/freertos_feature/resource/sdkconfig | 7 + example/freertos_feature/resource/sdkconfig.h | 7 + .../freertos_feature/software_timer/README.md | 3 + .../d2000_aarch32_test_software_timer.config | 7 + .../d2000_aarch64_test_software_timer.config | 7 + .../e2000d_aarch32_demo_software_timer.config | 7 + .../e2000d_aarch64_demo_software_timer.config | 7 + .../e2000q_aarch32_demo_software_timer.config | 7 + .../e2000q_aarch64_demo_software_timer.config | 7 + .../ft2004_aarch32_dsk_software_timer.config | 7 + .../ft2004_aarch64_dsk_software_timer.config | 7 + ...umpi_aarch32_firefly_software_timer.config | 7 + ...umpi_aarch64_firefly_software_timer.config | 7 + .../figs/tick_interrupt_source_config.png | Bin 0 -> 13001 bytes .../freertos_feature/software_timer/sdkconfig | 7 + .../software_timer/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_task.config | 7 + .../configs/d2000_aarch64_test_task.config | 7 + .../configs/e2000d_aarch32_demo_task.config | 7 + .../configs/e2000d_aarch64_demo_task.config | 7 + .../configs/e2000q_aarch32_demo_task.config | 7 + .../configs/e2000q_aarch64_demo_task.config | 7 + .../configs/ft2004_aarch32_dsk_task.config | 7 + .../configs/ft2004_aarch64_dsk_task.config | 7 + .../phytiumpi_aarch32_firefly_task.config | 7 + .../phytiumpi_aarch64_firefly_task.config | 7 + example/freertos_feature/task/sdkconfig | 7 + example/freertos_feature/task/sdkconfig.h | 7 + .../d2000_aarch32_test_task_notify.config | 7 + .../d2000_aarch64_test_task_notify.config | 7 + .../e2000d_aarch32_demo_task_notify.config | 7 + .../e2000d_aarch64_demo_task_notify.config | 7 + .../e2000q_aarch32_demo_task_notify.config | 7 + .../e2000q_aarch64_demo_task_notify.config | 7 + .../ft2004_aarch32_dsk_task_notify.config | 7 + .../ft2004_aarch64_dsk_task_notify.config | 7 + ...ytiumpi_aarch32_firefly_task_notify.config | 7 + ...ytiumpi_aarch64_firefly_task_notify.config | 7 + .../freertos_feature/task_notify/sdkconfig | 7 + .../freertos_feature/task_notify/sdkconfig.h | 7 + example/network/lwip_https/Kconfig | 4 + example/network/lwip_https/README.md | 152 + .../d2000_aarch32_test_lwip_https.config | 606 ++ .../d2000_aarch64_test_lwip_https.config | 595 ++ .../e2000d_aarch32_demo_lwip_https.config} | 288 +- .../e2000d_aarch64_demo_lwip_https.config} | 288 +- .../e2000q_aarch32_demo_lwip_https.config} | 288 +- .../e2000q_aarch64_demo_lwip_https.config} | 288 +- .../ft2004_aarch32_dsk_lwip_https.config | 606 ++ .../ft2004_aarch64_dsk_lwip_https.config | 595 ++ ...ytiumpi_aarch32_firefly_lwip_https.config} | 288 +- ...ytiumpi_aarch64_firefly_lwip_https.config} | 288 +- .../network/lwip_https/fig/https_client.png | Bin 0 -> 56683 bytes .../network/lwip_https/fig/https_server.png | Bin 0 -> 21774 bytes .../network/lwip_https/inc/https_example.h | 51 + example/network/lwip_https/main.c | 77 + example/network/lwip_https/makefile | 28 + example/network/lwip_https/sdkconfig | 606 ++ example/network/lwip_https/sdkconfig.h | 536 + example/network/lwip_https/src/cmd_https.c | 91 + .../network/lwip_https/src/https_example.c | 448 + example/network/lwip_https/tools/ssl_server | Bin 0 -> 566672 bytes .../d2000_aarch32_test_lwip_iperf.config | 7 + .../d2000_aarch64_test_lwip_iperf.config | 7 + .../e2000d_aarch32_demo_lwip_iperf.config | 7 + .../e2000d_aarch64_demo_lwip_iperf.config | 7 + .../e2000q_aarch32_demo_lwip_iperf.config | 7 + .../e2000q_aarch64_demo_lwip_iperf.config | 7 + .../ft2004_aarch32_dsk_lwip_iperf.config | 7 + .../ft2004_aarch64_dsk_lwip_iperf.config | 7 + ...hytiumpi_aarch32_firefly_lwip_iperf.config | 7 + ...hytiumpi_aarch64_firefly_lwip_iperf.config | 7 + example/network/lwip_iperf/sdkconfig | 7 + example/network/lwip_iperf/sdkconfig.h | 7 + .../d2000_aarch32_test_lwip_startup.config | 7 + .../d2000_aarch64_test_lwip_startup.config | 7 + .../e2000d_aarch32_demo_lwip_startup.config | 7 + .../e2000d_aarch64_demo_lwip_startup.config | 7 + .../e2000q_aarch32_demo_lwip_startup.config | 7 + .../e2000q_aarch64_demo_lwip_startup.config | 7 + .../ft2004_aarch32_dsk_lwip_startup.config | 7 + .../ft2004_aarch64_dsk_lwip_startup.config | 7 + ...tiumpi_aarch32_firefly_lwip_startup.config | 7 + ...tiumpi_aarch64_firefly_lwip_startup.config | 7 + example/network/lwip_startup/sdkconfig | 7 + example/network/lwip_startup/sdkconfig.h | 7 + .../lwip_startup/src/lwip_dhcp_example.c | 9 +- .../d2000_aarch32_test_udp_multicast.config | 7 + .../d2000_aarch64_test_udp_multicast.config | 7 + .../e2000d_aarch32_demo_udp_multicast.config | 7 + .../e2000d_aarch64_demo_udp_multicast.config | 7 + .../e2000q_aarch32_demo_udp_multicast.config | 7 + .../e2000q_aarch64_demo_udp_multicast.config | 7 + .../ft2004_aarch32_dsk_udp_multicast.config | 7 + .../ft2004_aarch64_dsk_udp_multicast.config | 7 + ...iumpi_aarch32_firefly_udp_multicast.config | 7 + ...iumpi_aarch64_firefly_udp_multicast.config | 7 + .../network/sockets/udp_multicast/sdkconfig | 7 + .../network/sockets/udp_multicast/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_wlan.config | 7 + .../configs/e2000d_aarch64_demo_wlan.config | 7 + .../configs/e2000q_aarch32_demo_wlan.config | 7 + .../configs/e2000q_aarch64_demo_wlan.config | 7 + example/network/wlan/sdkconfig | 7 + example/network/wlan/sdkconfig.h | 7 + .../can/configs/d2000_aarch32_test_can.config | 7 + .../can/configs/d2000_aarch64_test_can.config | 7 + .../configs/e2000d_aarch32_demo_can.config | 7 + .../configs/e2000d_aarch64_demo_can.config | 7 + .../configs/e2000q_aarch32_demo_can.config | 7 + .../configs/e2000q_aarch64_demo_can.config | 7 + .../can/configs/ft2004_aarch32_dsk_can.config | 7 + .../can/configs/ft2004_aarch64_dsk_can.config | 7 + example/peripheral/can/can/sdkconfig | 7 + example/peripheral/can/can/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_canfd.config | 7 + .../configs/e2000d_aarch64_demo_canfd.config | 7 + .../configs/e2000q_aarch32_demo_canfd.config | 7 + .../configs/e2000q_aarch64_demo_canfd.config | 7 + example/peripheral/can/canfd/sdkconfig | 7 + example/peripheral/can/canfd/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_ddma.config | 7 + .../configs/e2000d_aarch64_demo_ddma.config | 7 + .../configs/e2000q_aarch32_demo_ddma.config | 7 + .../configs/e2000q_aarch64_demo_ddma.config | 7 + .../phytiumpi_aarch32_firefly_ddma.config | 7 + .../phytiumpi_aarch64_firefly_ddma.config | 7 + example/peripheral/dma/ddma/sdkconfig | 7 + example/peripheral/dma/ddma/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_gdma.config | 7 + .../configs/e2000d_aarch64_demo_gdma.config | 7 + .../configs/e2000q_aarch32_demo_gdma.config | 7 + .../configs/e2000q_aarch64_demo_gdma.config | 7 + .../phytiumpi_aarch32_firefly_gdma.config | 7 + .../phytiumpi_aarch64_firefly_gdma.config | 7 + example/peripheral/dma/gdma/sdkconfig | 7 + example/peripheral/dma/gdma/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_gpio.config | 7 + .../configs/d2000_aarch64_test_gpio.config | 7 + .../configs/e2000d_aarch32_demo_gpio.config | 7 + .../configs/e2000d_aarch64_demo_gpio.config | 7 + .../configs/e2000q_aarch32_demo_gpio.config | 7 + .../configs/e2000q_aarch64_demo_gpio.config | 7 + .../phytiumpi_aarch32_firefly_gpio.config | 7 + .../phytiumpi_aarch64_firefly_gpio.config | 7 + example/peripheral/gpio/sdkconfig | 7 + example/peripheral/gpio/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_i2c.config | 7 + .../configs/e2000d_aarch64_demo_i2c.config | 7 + .../configs/e2000q_aarch32_demo_i2c.config | 7 + .../configs/e2000q_aarch64_demo_i2c.config | 7 + .../phytiumpi_aarch32_firefly_i2c.config | 7 + .../phytiumpi_aarch64_firefly_i2c.config | 7 + example/peripheral/i2c/sdkconfig | 7 + example/peripheral/i2c/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_i2s.config | 7 + .../configs/e2000d_aarch64_demo_i2s.config | 7 + .../configs/e2000q_aarch32_demo_i2s.config | 7 + .../configs/e2000q_aarch64_demo_i2s.config | 7 + example/peripheral/i2s/sdkconfig | 7 + example/peripheral/i2s/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_media.config | 21 +- .../configs/e2000d_aarch64_demo_media.config | 21 +- .../configs/e2000q_aarch32_demo_media.config | 21 +- .../configs/e2000q_aarch64_demo_media.config | 23 +- .../phytiumpi_aarch32_firefly_media.config | 21 +- .../phytiumpi_aarch64_firefly_media.config | 21 +- example/peripheral/media/lvgl_demo/sdkconfig | 33 +- .../peripheral/media/lvgl_demo/sdkconfig.h | 28 +- example/peripheral/media/lvgl_demo/src/cmd.c | 2 +- .../media/lvgl_demo/src/lv_demo_test.c | 90 +- .../configs/e2000d_aarch32_demo_media.config | 21 +- .../configs/e2000d_aarch64_demo_media.config | 23 +- .../configs/e2000q_aarch32_demo_media.config | 21 +- .../configs/e2000q_aarch64_demo_media.config | 23 +- .../phytiumpi_aarch32_firefly_media.config | 21 +- .../phytiumpi_aarch64_firefly_media.config | 21 +- example/peripheral/media/lvgl_indev/sdkconfig | 31 +- .../peripheral/media/lvgl_indev/sdkconfig.h | 26 +- example/peripheral/media/lvgl_indev/src/cmd.c | 1 - .../media/lvgl_indev/src/lv_indev_test.c | 88 +- .../configs/e2000d_aarch32_demo_media.config | 21 +- .../configs/e2000d_aarch64_demo_media.config | 23 +- .../configs/e2000q_aarch32_demo_media.config | 21 +- .../configs/e2000q_aarch64_demo_media.config | 23 +- .../phytiumpi_aarch32_firefly_media.config | 21 +- .../phytiumpi_aarch64_firefly_media.config | 21 +- example/peripheral/media/lvgl_ui/sdkconfig | 21 +- example/peripheral/media/lvgl_ui/sdkconfig.h | 18 +- example/peripheral/media/lvgl_ui/src/cmd.c | 1 - .../media/lvgl_ui/src/lv_indev_test.c | 86 +- .../configs/e2000d_aarch32_demo_media.config | 23 +- .../configs/e2000d_aarch64_demo_media.config | 25 +- .../configs/e2000q_aarch32_demo_media.config | 23 +- .../configs/e2000q_aarch64_demo_media.config | 25 +- .../phytiumpi_aarch32_firefly_media.config | 23 +- .../phytiumpi_aarch64_firefly_media.config | 23 +- example/peripheral/media/media_test/sdkconfig | 33 +- .../peripheral/media/media_test/sdkconfig.h | 28 +- .../media/media_test/src/cmd_media.c | 1 - .../media/media_test/src/media_example.c | 91 +- .../configs/e2000d_aarch32_demo_pwm.config | 7 + .../configs/e2000d_aarch64_demo_pwm.config | 7 + .../configs/e2000q_aarch32_demo_pwm.config | 7 + .../configs/e2000q_aarch64_demo_pwm.config | 7 + .../phytiumpi_aarch32_firefly_pwm.config | 7 + .../phytiumpi_aarch64_firefly_pwm.config | 7 + example/peripheral/pwm/sdkconfig | 7 + example/peripheral/pwm/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_qspi.config | 7 + .../configs/d2000_aarch64_test_qspi.config | 7 + .../configs/e2000d_aarch32_demo_qspi.config | 7 + .../configs/e2000d_aarch64_demo_qspi.config | 7 + .../configs/e2000q_aarch32_demo_qspi.config | 7 + .../configs/e2000q_aarch64_demo_qspi.config | 7 + .../configs/ft2004_aarch32_dsk_qspi.config | 7 + .../configs/ft2004_aarch64_dsk_qspi.config | 7 + .../phytiumpi_aarch32_firefly_qspi.config | 7 + .../phytiumpi_aarch64_firefly_qspi.config | 7 + example/peripheral/qspi/main.c | 4 +- example/peripheral/qspi/sdkconfig | 7 + example/peripheral/qspi/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_sdif.config | 7 + .../configs/e2000d_aarch64_demo_sdif.config | 7 + .../configs/e2000q_aarch32_demo_sdif.config | 7 + .../configs/e2000q_aarch64_demo_sdif.config | 7 + example/peripheral/sdif/sdkconfig | 7 + example/peripheral/sdif/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_spi.config | 7 + .../configs/e2000d_aarch64_demo_spi.config | 7 + .../configs/e2000q_aarch32_demo_spi.config | 7 + .../configs/e2000q_aarch64_demo_spi.config | 7 + .../phytiumpi_aarch32_firefly_spi.config | 7 + .../phytiumpi_aarch64_firefly_spi.config | 7 + example/peripheral/spi/sdkconfig | 7 + example/peripheral/spi/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_timer.config | 7 + .../configs/e2000d_aarch64_demo_timer.config | 7 + .../configs/e2000q_aarch32_demo_timer.config | 7 + .../configs/e2000q_aarch64_demo_timer.config | 7 + .../phytiumpi_aarch32_firefly_timer.config | 7 + .../phytiumpi_aarch64_firefly_timer.config | 7 + example/peripheral/timer_tacho/sdkconfig | 7 + example/peripheral/timer_tacho/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_pusb2.config | 7 + .../configs/e2000d_aarch64_demo_pusb2.config | 7 + .../configs/e2000q_aarch32_demo_pusb2.config | 7 + .../configs/e2000q_aarch64_demo_pusb2.config | 7 + example/peripheral/usb/pusb2_device/main.c | 2 +- example/peripheral/usb/pusb2_device/sdkconfig | 7 + .../peripheral/usb/pusb2_device/sdkconfig.h | 7 + .../usb/pusb2_device/src/cmd_pusb2.c | 5 +- .../phytiumpi_aarch32_firefly_pusb2.config | 7 + .../phytiumpi_aarch64_firefly_pusb2.config | 7 + example/peripheral/usb/pusb2_host/sdkconfig | 7 + example/peripheral/usb/pusb2_host/sdkconfig.h | 7 + .../d2000_aarch32_test_cherry_usb.config | 7 + .../d2000_aarch64_test_cherry_usb.config | 7 + .../e2000d_aarch32_demo_cherry_usb.config | 7 + .../e2000d_aarch64_demo_cherry_usb.config | 7 + .../e2000q_aarch32_demo_cherry_usb.config | 7 + .../e2000q_aarch64_demo_cherry_usb.config | 7 + example/peripheral/usb/xhci_pcie/sdkconfig | 7 + example/peripheral/usb/xhci_pcie/sdkconfig.h | 7 + .../e2000d_aarch32_demo_cherry_usb.config | 7 + .../e2000d_aarch64_demo_cherry_usb.config | 7 + .../e2000q_aarch32_demo_cherry_usb.config | 7 + .../e2000q_aarch64_demo_cherry_usb.config | 7 + ...hytiumpi_aarch32_firefly_cherry_usb.config | 7 + ...hytiumpi_aarch64_firefly_cherry_usb.config | 7 + .../peripheral/usb/xhci_platform/sdkconfig | 7 + .../peripheral/usb/xhci_platform/sdkconfig.h | 7 + .../wdt/configs/d2000_aarch32_test_wdt.config | 7 + .../wdt/configs/d2000_aarch64_test_wdt.config | 7 + .../configs/e2000d_aarch32_demo_wdt.config | 7 + .../configs/e2000d_aarch64_demo_wdt.config | 7 + .../configs/e2000q_aarch32_demo_wdt.config | 7 + .../configs/e2000q_aarch64_demo_wdt.config | 7 + .../wdt/configs/ft2004_aarch32_dsk_wdt.config | 7 + .../wdt/configs/ft2004_aarch64_dsk_wdt.config | 7 + .../phytiumpi_aarch32_firefly_wdt.config | 7 + .../phytiumpi_aarch64_firefly_wdt.config | 7 + example/peripheral/wdt/sdkconfig | 7 + example/peripheral/wdt/sdkconfig.h | 7 + .../configs/e2000d_aarch32_demo_fatfs.config | 7 + .../configs/e2000d_aarch64_demo_fatfs.config | 7 + .../configs/e2000q_aarch32_demo_fatfs.config | 7 + .../configs/e2000q_aarch64_demo_fatfs.config | 7 + .../phytiumpi_aarch32_firefly_fatfs.config | 7 + .../phytiumpi_aarch64_firefly_fatfs.config | 7 + example/storage/fatfs/sdkconfig | 7 + example/storage/fatfs/sdkconfig.h | 7 + .../d2000_aarch32_test_qspi_spiffs.config | 7 + .../d2000_aarch64_test_qspi_spiffs.config | 7 + .../e2000d_aarch32_demo_qspi_spiffs.config | 7 + .../e2000d_aarch64_demo_qspi_spiffs.config | 7 + .../e2000q_aarch32_demo_qspi_spiffs.config | 7 + .../e2000q_aarch64_demo_qspi_spiffs.config | 7 + .../ft2004_aarch32_dsk_qspi_spiffs.config | 7 + .../ft2004_aarch64_dsk_qspi_spiffs.config | 7 + ...ytiumpi_aarch32_firefly_qspi_spiffs.config | 7 + ...ytiumpi_aarch64_firefly_qspi_spiffs.config | 7 + example/storage/qspi_spiffs/sdkconfig | 7 + example/storage/qspi_spiffs/sdkconfig.h | 7 + .../e2000d_aarch32_demo_spi_spiffs.config | 7 + .../e2000d_aarch64_demo_spi_spiffs.config | 7 + .../e2000q_aarch32_demo_spi_spiffs.config | 7 + .../e2000q_aarch64_demo_spi_spiffs.config | 7 + ...hytiumpi_aarch32_firefly_spi_spiffs.config | 7 + ...hytiumpi_aarch64_firefly_spi_spiffs.config | 7 + example/storage/spim_spiffs/sdkconfig | 7 + example/storage/spim_spiffs/sdkconfig.h | 7 + example/system/amp/README.md | 2 +- .../amp/openamp/common/openamp_configs.h | 15 +- ...00_aarch32_test_openamp_device_core.config | 6 + ...00_aarch64_test_openamp_device_core.config | 6 + ...0d_aarch32_demo_openamp_device_core.config | 5 + ...0d_aarch64_demo_openamp_device_core.config | 5 + ...0q_aarch32_demo_openamp_device_core.config | 5 + ...0q_aarch64_demo_openamp_device_core.config | 5 + ...aarch32_firefly_openamp_device_core.config | 5 + ...aarch64_firefly_openamp_device_core.config | 5 + .../system/amp/openamp/device_core/sdkconfig | 16 +- .../amp/openamp/device_core/sdkconfig.h | 16 +- .../system/amp/openamp/driver_core/README.md | 22 +- .../amp/openamp/driver_core/amp_config.json | 56 +- ...00_aarch32_test_openamp_driver_core.config | 25 +- ...00_aarch64_test_openamp_driver_core.config | 25 +- ...0d_aarch32_demo_openamp_driver_core.config | 22 +- ...0d_aarch64_demo_openamp_driver_core.config | 20 +- ...0q_aarch32_demo_openamp_driver_core.config | 22 +- ...0q_aarch64_demo_openamp_driver_core.config | 20 +- ...aarch32_firefly_openamp_driver_core.config | 22 +- ...aarch64_firefly_openamp_driver_core.config | 20 +- .../openamp/driver_core/fig/1677585960509.png | Bin 114715 -> 0 bytes .../driver_core/fig/20230512192325.png | Bin 257953 -> 0 bytes .../driver_core/fig/20230512195526.png | Bin 114642 -> 0 bytes .../driver_core/fig/20230512200435.png | Bin 215850 -> 0 bytes ...{20231017165755.png => Test32_Results.png} | Bin ...{20231017160632.png => Test64_Results.png} | Bin .../fig/e2000_aarch32_openamp_startup.png | Bin 251503 -> 133687 bytes .../fig/e2000_aarch64_openamp_startup.png | Bin 242426 -> 136696 bytes .../amp/openamp/driver_core/fig/openamp32.png | Bin 0 -> 85046 bytes .../driver_core/fig/openamp32_auto.png | Bin 0 -> 213806 bytes .../amp/openamp/driver_core/fig/openamp64.png | Bin 0 -> 84465 bytes .../driver_core/fig/openamp64_auto.png | Bin 0 -> 226121 bytes .../system/amp/openamp/driver_core/sdkconfig | 31 +- .../amp/openamp/driver_core/sdkconfig.h | 30 +- ...2000_aarch32_test_openamp_for_linux.config | 8 + ...2000_aarch64_test_openamp_for_linux.config | 8 + ...000d_aarch32_demo_openamp_for_linux.config | 5 + ...000d_aarch64_demo_openamp_for_linux.config | 5 + ...000q_aarch32_demo_openamp_for_linux.config | 5 + ...000q_aarch64_demo_openamp_for_linux.config | 5 + ...i_aarch32_firefly_openamp_for_linux.config | 5 + ...i_aarch64_firefly_openamp_for_linux.config | 5 + .../system/amp/openamp_for_linux/sdkconfig | 5 + .../system/amp/openamp_for_linux/sdkconfig.h | 5 + .../configs/d2000_aarch32_test_atomic.config | 7 + .../configs/d2000_aarch64_test_atomic.config | 7 + .../configs/e2000d_aarch32_demo_atomic.config | 7 + .../configs/e2000d_aarch64_demo_atomic.config | 7 + .../configs/e2000q_aarch32_demo_atomic.config | 7 + .../configs/e2000q_aarch64_demo_atomic.config | 7 + .../configs/ft2004_aarch32_dsk_atomic.config | 7 + .../configs/ft2004_aarch64_dsk_atomic.config | 7 + .../phytiumpi_aarch32_firefly_atomic.config | 7 + .../phytiumpi_aarch64_firefly_atomic.config | 7 + example/system/atomic/sdkconfig | 7 + example/system/atomic/sdkconfig.h | 7 + .../d2000_aarch32_test_exception.config | 7 + .../d2000_aarch64_test_exception.config | 7 + .../e2000d_aarch32_demo_exception.config | 7 + .../e2000d_aarch64_demo_exception.config | 7 + .../e2000q_aarch32_demo_exception.config | 7 + .../e2000q_aarch64_demo_exception.config | 7 + .../ft2004_aarch32_dsk_exception.config | 7 + .../ft2004_aarch64_dsk_exception.config | 7 + ...phytiumpi_aarch32_firefly_exception.config | 7 + ...phytiumpi_aarch64_firefly_exception.config | 7 + example/system/exception_debug/main.c | 8 +- example/system/exception_debug/sdkconfig | 7 + example/system/exception_debug/sdkconfig.h | 7 + .../exception_debug/src/exception_test.c | 2 - ...d2000_aarch32_test_nested_interrupt.config | 7 + ...d2000_aarch64_test_nested_interrupt.config | 7 + ...2000d_aarch32_demo_nested_interrupt.config | 7 + ...2000d_aarch64_demo_nested_interrupt.config | 7 + ...2000q_aarch32_demo_nested_interrupt.config | 7 + ...2000q_aarch64_demo_nested_interrupt.config | 7 + ...ft2004_aarch32_dsk_nested_interrupt.config | 7 + ...ft2004_aarch64_dsk_nested_interrupt.config | 7 + ...pi_aarch32_firefly_nested_interrupt.config | 7 + ...pi_aarch64_firefly_nested_interrupt.config | 7 + example/system/nested_interrupt/sdkconfig | 7 + example/system/nested_interrupt/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_posix.config | 7 + .../configs/d2000_aarch64_test_posix.config | 7 + .../configs/e2000d_aarch32_demo_posix.config | 7 + .../configs/e2000d_aarch64_demo_posix.config | 7 + .../configs/e2000q_aarch32_demo_posix.config | 7 + .../configs/e2000q_aarch64_demo_posix.config | 7 + .../configs/ft2004_aarch32_dsk_posix.config | 7 + .../configs/ft2004_aarch64_dsk_posix.config | 7 + .../phytiumpi_aarch32_firefly_posix.config | 7 + .../phytiumpi_aarch64_firefly_posix.config | 7 + example/system/posix/sdkconfig | 7 + example/system/posix/sdkconfig.h | 7 + .../configs/d2000_aarch32_test_eg.config | 7 + .../configs/d2000_aarch64_test_eg.config | 7 + .../configs/e2000d_aarch32_demo_eg.config | 7 + .../configs/e2000d_aarch64_demo_eg.config | 7 + .../configs/e2000q_aarch32_demo_eg.config | 7 + .../configs/e2000q_aarch64_demo_eg.config | 7 + .../configs/ft2004_aarch32_dsk_eg.config | 7 + .../configs/ft2004_aarch64_dsk_eg.config | 7 + .../phytiumpi_aarch32_firefly_eg.config | 7 + .../phytiumpi_aarch64_firefly_eg.config | 7 + example/template/sdkconfig | 7 + example/template/sdkconfig.h | 7 + install.py | 2 +- third-party/freertos/freertos.kconfig | 17 +- .../portable/GCC/ft_platform/aarch64/port.c | 34 +- .../freertos/portable/freertos_configs.c | 24 +- third-party/include.mk | 4 + third-party/letter-shell-3.1/Kconfig | 15 + .../port/pl011/fpl011_os_port.c | 57 +- third-party/lvgl-8.3/port/lv_port_disp.c | 6 +- third-party/mbedtls-3.6/Kconfig | 3 + third-party/mbedtls-3.6/include.mk | 14 + third-party/mbedtls-3.6/include/.gitignore | 4 + .../mbedtls-3.6/include/CMakeLists.txt | 16 + third-party/mbedtls-3.6/include/mbedtls/aes.h | 443 + .../mbedtls-3.6/include/mbedtls/aesni.h | 143 + .../mbedtls-3.6/include/mbedtls/arc4.h | 174 + .../mbedtls-3.6/include/mbedtls/asn1.h | 383 + .../mbedtls-3.6/include/mbedtls/asn1write.h | 274 + .../mbedtls-3.6/include/mbedtls/base64.h | 120 + .../mbedtls-3.6/include/mbedtls/bignum.h | 809 ++ .../mbedtls-3.6/include/mbedtls/blowfish.h | 230 + .../mbedtls-3.6/include/mbedtls/bn_mul.h | 924 ++ .../mbedtls-3.6/include/mbedtls/camellia.h | 262 + third-party/mbedtls-3.6/include/mbedtls/ccm.h | 207 + .../mbedtls-3.6/include/mbedtls/certs.h | 131 + .../include/mbedtls/check_config.h | 753 ++ .../mbedtls-3.6/include/mbedtls/cipher.h | 777 ++ .../include/mbedtls/cipher_internal.h | 135 + .../mbedtls-3.6/include/mbedtls/cmac.h | 239 + .../mbedtls-3.6/include/mbedtls/compat-1.3.h | 2555 +++++ .../mbedtls-3.6/include/mbedtls/config.h | 2976 ++++++ .../mbedtls-3.6/include/mbedtls/ctr_drbg.h | 543 ++ .../mbedtls-3.6/include/mbedtls/debug.h | 254 + third-party/mbedtls-3.6/include/mbedtls/des.h | 382 + third-party/mbedtls-3.6/include/mbedtls/dhm.h | 1086 +++ .../mbedtls-3.6/include/mbedtls/ecdh.h | 308 + .../mbedtls-3.6/include/mbedtls/ecdsa.h | 426 + .../mbedtls-3.6/include/mbedtls/ecjpake.h | 285 + third-party/mbedtls-3.6/include/mbedtls/ecp.h | 736 ++ .../include/mbedtls/ecp_internal.h | 324 + .../mbedtls-3.6/include/mbedtls/entropy.h | 316 + .../include/mbedtls/entropy_poll.h | 135 + .../mbedtls-3.6/include/mbedtls/error.h | 149 + third-party/mbedtls-3.6/include/mbedtls/gcm.h | 320 + .../mbedtls-3.6/include/mbedtls/havege.h | 106 + .../mbedtls-3.6/include/mbedtls/hmac_drbg.h | 495 + third-party/mbedtls-3.6/include/mbedtls/md.h | 480 + third-party/mbedtls-3.6/include/mbedtls/md2.h | 334 + third-party/mbedtls-3.6/include/mbedtls/md4.h | 339 + third-party/mbedtls-3.6/include/mbedtls/md5.h | 339 + .../mbedtls-3.6/include/mbedtls/md_internal.h | 140 + .../include/mbedtls/memory_buffer_alloc.h | 176 + third-party/mbedtls-3.6/include/mbedtls/net.h | 62 + .../mbedtls-3.6/include/mbedtls/net_sockets.h | 264 + third-party/mbedtls-3.6/include/mbedtls/oid.h | 614 ++ .../mbedtls-3.6/include/mbedtls/padlock.h | 139 + third-party/mbedtls-3.6/include/mbedtls/pem.h | 161 + third-party/mbedtls-3.6/include/mbedtls/pk.h | 647 ++ .../mbedtls-3.6/include/mbedtls/pk_internal.h | 140 + .../mbedtls-3.6/include/mbedtls/pkcs11.h | 199 + .../mbedtls-3.6/include/mbedtls/pkcs12.h | 155 + .../mbedtls-3.6/include/mbedtls/pkcs5.h | 130 + .../mbedtls-3.6/include/mbedtls/platform.h | 373 + .../include/mbedtls/platform_time.h | 107 + .../mbedtls-3.6/include/mbedtls/ripemd160.h | 264 + third-party/mbedtls-3.6/include/mbedtls/rsa.h | 1170 +++ .../include/mbedtls/rsa_internal.h | 251 + .../mbedtls-3.6/include/mbedtls/sha1.h | 347 + .../mbedtls-3.6/include/mbedtls/sha256.h | 303 + .../mbedtls-3.6/include/mbedtls/sha512.h | 305 + third-party/mbedtls-3.6/include/mbedtls/ssl.h | 2697 ++++++ .../mbedtls-3.6/include/mbedtls/ssl_cache.h | 175 + .../include/mbedtls/ssl_ciphersuites.h | 517 + .../mbedtls-3.6/include/mbedtls/ssl_cookie.h | 140 + .../include/mbedtls/ssl_internal.h | 821 ++ .../mbedtls-3.6/include/mbedtls/ssl_ticket.h | 167 + .../mbedtls-3.6/include/mbedtls/threading.h | 139 + .../mbedtls-3.6/include/mbedtls/timing.h | 186 + .../mbedtls-3.6/include/mbedtls/version.h | 137 + .../mbedtls-3.6/include/mbedtls/x509.h | 358 + .../mbedtls-3.6/include/mbedtls/x509_crl.h | 199 + .../mbedtls-3.6/include/mbedtls/x509_crt.h | 710 ++ .../mbedtls-3.6/include/mbedtls/x509_csr.h | 332 + .../mbedtls-3.6/include/mbedtls/xtea.h | 166 + third-party/mbedtls-3.6/library/.gitignore | 4 + .../mbedtls-3.6/library/CMakeLists.txt | 169 + third-party/mbedtls-3.6/library/Makefile | 172 + third-party/mbedtls-3.6/library/aes.c | 1565 +++ third-party/mbedtls-3.6/library/aesni.c | 489 + third-party/mbedtls-3.6/library/arc4.c | 230 + third-party/mbedtls-3.6/library/asn1parse.c | 418 + third-party/mbedtls-3.6/library/asn1write.c | 446 + third-party/mbedtls-3.6/library/base64.c | 427 + third-party/mbedtls-3.6/library/bignum.c | 2708 ++++++ third-party/mbedtls-3.6/library/blowfish.c | 681 ++ third-party/mbedtls-3.6/library/camellia.c | 1097 +++ third-party/mbedtls-3.6/library/ccm.c | 504 + third-party/mbedtls-3.6/library/certs.c | 463 + third-party/mbedtls-3.6/library/cipher.c | 948 ++ third-party/mbedtls-3.6/library/cipher_wrap.c | 1476 +++ third-party/mbedtls-3.6/library/cmac.c | 1107 +++ third-party/mbedtls-3.6/library/ctr_drbg.c | 696 ++ third-party/mbedtls-3.6/library/debug.c | 425 + third-party/mbedtls-3.6/library/des.c | 1086 +++ third-party/mbedtls-3.6/library/dhm.c | 716 ++ third-party/mbedtls-3.6/library/ecdh.c | 305 + third-party/mbedtls-3.6/library/ecdsa.c | 575 ++ third-party/mbedtls-3.6/library/ecjpake.c | 1131 +++ third-party/mbedtls-3.6/library/ecp.c | 2633 +++++ third-party/mbedtls-3.6/library/ecp_curves.c | 1354 +++ third-party/mbedtls-3.6/library/entropy.c | 755 ++ .../mbedtls-3.6/library/entropy_poll.c | 254 + third-party/mbedtls-3.6/library/error.c | 850 ++ third-party/mbedtls-3.6/library/gcm.c | 983 ++ third-party/mbedtls-3.6/library/havege.c | 282 + third-party/mbedtls-3.6/library/hmac_drbg.c | 660 ++ third-party/mbedtls-3.6/library/md.c | 503 + third-party/mbedtls-3.6/library/md2.c | 395 + third-party/mbedtls-3.6/library/md4.c | 503 + third-party/mbedtls-3.6/library/md5.c | 530 + third-party/mbedtls-3.6/library/md_wrap.c | 611 ++ .../mbedtls-3.6/library/memory_buffer_alloc.c | 779 ++ third-party/mbedtls-3.6/library/net_sockets.c | 625 ++ third-party/mbedtls-3.6/library/oid.c | 780 ++ third-party/mbedtls-3.6/library/padlock.c | 195 + third-party/mbedtls-3.6/library/pem.c | 520 + third-party/mbedtls-3.6/library/pk.c | 407 + third-party/mbedtls-3.6/library/pk_wrap.c | 551 ++ third-party/mbedtls-3.6/library/pkcs11.c | 265 + third-party/mbedtls-3.6/library/pkcs12.c | 394 + third-party/mbedtls-3.6/library/pkcs5.c | 446 + third-party/mbedtls-3.6/library/pkparse.c | 1485 +++ third-party/mbedtls-3.6/library/pkwrite.c | 567 ++ third-party/mbedtls-3.6/library/platform.c | 370 + third-party/mbedtls-3.6/library/ripemd160.c | 587 ++ third-party/mbedtls-3.6/library/rsa.c | 2602 +++++ .../mbedtls-3.6/library/rsa_internal.c | 512 + third-party/mbedtls-3.6/library/sha1.c | 584 ++ third-party/mbedtls-3.6/library/sha256.c | 616 ++ third-party/mbedtls-3.6/library/sha512.c | 653 ++ third-party/mbedtls-3.6/library/ssl_cache.c | 352 + .../mbedtls-3.6/library/ssl_ciphersuites.c | 1915 ++++ third-party/mbedtls-3.6/library/ssl_cli.c | 3801 ++++++++ third-party/mbedtls-3.6/library/ssl_cookie.c | 283 + third-party/mbedtls-3.6/library/ssl_srv.c | 4160 ++++++++ third-party/mbedtls-3.6/library/ssl_ticket.c | 534 + third-party/mbedtls-3.6/library/ssl_tls.c | 8604 +++++++++++++++++ third-party/mbedtls-3.6/library/threading.c | 180 + third-party/mbedtls-3.6/library/timing.c | 560 ++ third-party/mbedtls-3.6/library/version.c | 75 + .../mbedtls-3.6/library/version_features.c | 759 ++ third-party/mbedtls-3.6/library/x509.c | 1121 +++ third-party/mbedtls-3.6/library/x509_create.c | 365 + third-party/mbedtls-3.6/library/x509_crl.c | 801 ++ third-party/mbedtls-3.6/library/x509_crt.c | 2506 +++++ third-party/mbedtls-3.6/library/x509_csr.c | 448 + .../mbedtls-3.6/library/x509write_crt.c | 551 ++ .../mbedtls-3.6/library/x509write_csr.c | 331 + third-party/mbedtls-3.6/library/xtea.c | 306 + third-party/mbedtls-3.6/makefile | 5 + third-party/mbedtls-3.6/mbedtls.kconfig | 3 + third-party/mbedtls-3.6/mbedtls_freertos.mk | 8 + .../mbedtls-3.6/ports/inc/tls_certificate.h | 28 + third-party/mbedtls-3.6/ports/inc/tls_net.h | 224 + .../mbedtls-3.6/ports/src/tls_certificate.c | 47 + third-party/mbedtls-3.6/ports/src/tls_net.c | 508 + third-party/mbedtls-3.6/src.mk | 11 + third-party/third-party.kconfig | 11 + third-party/thirdparty.mk | 11 + 640 files changed, 111057 insertions(+), 589 deletions(-) create mode 100644 example/freertos_feature/software_timer/figs/tick_interrupt_source_config.png create mode 100644 example/network/lwip_https/Kconfig create mode 100644 example/network/lwip_https/README.md create mode 100644 example/network/lwip_https/configs/d2000_aarch32_test_lwip_https.config create mode 100644 example/network/lwip_https/configs/d2000_aarch64_test_lwip_https.config rename example/{peripheral/media/media_test/configs/e2000d_aarch32_demo_freertos.config => network/lwip_https/configs/e2000d_aarch32_demo_lwip_https.config} (58%) rename example/{peripheral/media/media_test/configs/e2000d_aarch64_demo_freertos.config => network/lwip_https/configs/e2000d_aarch64_demo_lwip_https.config} (57%) rename example/{peripheral/media/media_test/configs/e2000q_aarch32_demo_freertos.config => network/lwip_https/configs/e2000q_aarch32_demo_lwip_https.config} (58%) rename example/{peripheral/media/media_test/configs/e2000q_aarch64_demo_freertos.config => network/lwip_https/configs/e2000q_aarch64_demo_lwip_https.config} (57%) create mode 100644 example/network/lwip_https/configs/ft2004_aarch32_dsk_lwip_https.config create mode 100644 example/network/lwip_https/configs/ft2004_aarch64_dsk_lwip_https.config rename example/{peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_freertos.config => network/lwip_https/configs/phytiumpi_aarch32_firefly_lwip_https.config} (58%) rename example/{peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_freertos.config => network/lwip_https/configs/phytiumpi_aarch64_firefly_lwip_https.config} (57%) create mode 100644 example/network/lwip_https/fig/https_client.png create mode 100644 example/network/lwip_https/fig/https_server.png create mode 100644 example/network/lwip_https/inc/https_example.h create mode 100644 example/network/lwip_https/main.c create mode 100644 example/network/lwip_https/makefile create mode 100644 example/network/lwip_https/sdkconfig create mode 100644 example/network/lwip_https/sdkconfig.h create mode 100644 example/network/lwip_https/src/cmd_https.c create mode 100644 example/network/lwip_https/src/https_example.c create mode 100644 example/network/lwip_https/tools/ssl_server delete mode 100644 example/system/amp/openamp/driver_core/fig/1677585960509.png delete mode 100644 example/system/amp/openamp/driver_core/fig/20230512192325.png delete mode 100644 example/system/amp/openamp/driver_core/fig/20230512195526.png delete mode 100644 example/system/amp/openamp/driver_core/fig/20230512200435.png rename example/system/amp/openamp/driver_core/fig/{20231017165755.png => Test32_Results.png} (100%) rename example/system/amp/openamp/driver_core/fig/{20231017160632.png => Test64_Results.png} (100%) create mode 100644 example/system/amp/openamp/driver_core/fig/openamp32.png create mode 100644 example/system/amp/openamp/driver_core/fig/openamp32_auto.png create mode 100644 example/system/amp/openamp/driver_core/fig/openamp64.png create mode 100644 example/system/amp/openamp/driver_core/fig/openamp64_auto.png create mode 100644 third-party/mbedtls-3.6/Kconfig create mode 100644 third-party/mbedtls-3.6/include.mk create mode 100644 third-party/mbedtls-3.6/include/.gitignore create mode 100644 third-party/mbedtls-3.6/include/CMakeLists.txt create mode 100644 third-party/mbedtls-3.6/include/mbedtls/aes.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/aesni.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/arc4.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/asn1.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/asn1write.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/base64.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/bignum.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/blowfish.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/bn_mul.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/camellia.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ccm.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/certs.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/check_config.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/cipher.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/cipher_internal.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/cmac.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/compat-1.3.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/config.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ctr_drbg.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/debug.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/des.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/dhm.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ecdh.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ecdsa.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ecjpake.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ecp.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ecp_internal.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/entropy.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/entropy_poll.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/error.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/gcm.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/havege.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/hmac_drbg.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/md.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/md2.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/md4.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/md5.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/md_internal.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/memory_buffer_alloc.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/net.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/net_sockets.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/oid.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/padlock.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/pem.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/pk.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/pk_internal.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/pkcs11.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/pkcs12.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/pkcs5.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/platform.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/platform_time.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ripemd160.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/rsa.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/rsa_internal.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/sha1.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/sha256.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/sha512.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ssl.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ssl_cache.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ssl_ciphersuites.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ssl_cookie.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ssl_internal.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/ssl_ticket.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/threading.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/timing.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/version.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/x509.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/x509_crl.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/x509_crt.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/x509_csr.h create mode 100644 third-party/mbedtls-3.6/include/mbedtls/xtea.h create mode 100644 third-party/mbedtls-3.6/library/.gitignore create mode 100644 third-party/mbedtls-3.6/library/CMakeLists.txt create mode 100644 third-party/mbedtls-3.6/library/Makefile create mode 100644 third-party/mbedtls-3.6/library/aes.c create mode 100644 third-party/mbedtls-3.6/library/aesni.c create mode 100644 third-party/mbedtls-3.6/library/arc4.c create mode 100644 third-party/mbedtls-3.6/library/asn1parse.c create mode 100644 third-party/mbedtls-3.6/library/asn1write.c create mode 100644 third-party/mbedtls-3.6/library/base64.c create mode 100644 third-party/mbedtls-3.6/library/bignum.c create mode 100644 third-party/mbedtls-3.6/library/blowfish.c create mode 100644 third-party/mbedtls-3.6/library/camellia.c create mode 100644 third-party/mbedtls-3.6/library/ccm.c create mode 100644 third-party/mbedtls-3.6/library/certs.c create mode 100644 third-party/mbedtls-3.6/library/cipher.c create mode 100644 third-party/mbedtls-3.6/library/cipher_wrap.c create mode 100644 third-party/mbedtls-3.6/library/cmac.c create mode 100644 third-party/mbedtls-3.6/library/ctr_drbg.c create mode 100644 third-party/mbedtls-3.6/library/debug.c create mode 100644 third-party/mbedtls-3.6/library/des.c create mode 100644 third-party/mbedtls-3.6/library/dhm.c create mode 100644 third-party/mbedtls-3.6/library/ecdh.c create mode 100644 third-party/mbedtls-3.6/library/ecdsa.c create mode 100644 third-party/mbedtls-3.6/library/ecjpake.c create mode 100644 third-party/mbedtls-3.6/library/ecp.c create mode 100644 third-party/mbedtls-3.6/library/ecp_curves.c create mode 100644 third-party/mbedtls-3.6/library/entropy.c create mode 100644 third-party/mbedtls-3.6/library/entropy_poll.c create mode 100644 third-party/mbedtls-3.6/library/error.c create mode 100644 third-party/mbedtls-3.6/library/gcm.c create mode 100644 third-party/mbedtls-3.6/library/havege.c create mode 100644 third-party/mbedtls-3.6/library/hmac_drbg.c create mode 100644 third-party/mbedtls-3.6/library/md.c create mode 100644 third-party/mbedtls-3.6/library/md2.c create mode 100644 third-party/mbedtls-3.6/library/md4.c create mode 100644 third-party/mbedtls-3.6/library/md5.c create mode 100644 third-party/mbedtls-3.6/library/md_wrap.c create mode 100644 third-party/mbedtls-3.6/library/memory_buffer_alloc.c create mode 100644 third-party/mbedtls-3.6/library/net_sockets.c create mode 100644 third-party/mbedtls-3.6/library/oid.c create mode 100644 third-party/mbedtls-3.6/library/padlock.c create mode 100644 third-party/mbedtls-3.6/library/pem.c create mode 100644 third-party/mbedtls-3.6/library/pk.c create mode 100644 third-party/mbedtls-3.6/library/pk_wrap.c create mode 100644 third-party/mbedtls-3.6/library/pkcs11.c create mode 100644 third-party/mbedtls-3.6/library/pkcs12.c create mode 100644 third-party/mbedtls-3.6/library/pkcs5.c create mode 100644 third-party/mbedtls-3.6/library/pkparse.c create mode 100644 third-party/mbedtls-3.6/library/pkwrite.c create mode 100644 third-party/mbedtls-3.6/library/platform.c create mode 100644 third-party/mbedtls-3.6/library/ripemd160.c create mode 100644 third-party/mbedtls-3.6/library/rsa.c create mode 100644 third-party/mbedtls-3.6/library/rsa_internal.c create mode 100644 third-party/mbedtls-3.6/library/sha1.c create mode 100644 third-party/mbedtls-3.6/library/sha256.c create mode 100644 third-party/mbedtls-3.6/library/sha512.c create mode 100644 third-party/mbedtls-3.6/library/ssl_cache.c create mode 100644 third-party/mbedtls-3.6/library/ssl_ciphersuites.c create mode 100644 third-party/mbedtls-3.6/library/ssl_cli.c create mode 100644 third-party/mbedtls-3.6/library/ssl_cookie.c create mode 100644 third-party/mbedtls-3.6/library/ssl_srv.c create mode 100644 third-party/mbedtls-3.6/library/ssl_ticket.c create mode 100644 third-party/mbedtls-3.6/library/ssl_tls.c create mode 100644 third-party/mbedtls-3.6/library/threading.c create mode 100644 third-party/mbedtls-3.6/library/timing.c create mode 100644 third-party/mbedtls-3.6/library/version.c create mode 100644 third-party/mbedtls-3.6/library/version_features.c create mode 100644 third-party/mbedtls-3.6/library/x509.c create mode 100644 third-party/mbedtls-3.6/library/x509_create.c create mode 100644 third-party/mbedtls-3.6/library/x509_crl.c create mode 100644 third-party/mbedtls-3.6/library/x509_crt.c create mode 100644 third-party/mbedtls-3.6/library/x509_csr.c create mode 100644 third-party/mbedtls-3.6/library/x509write_crt.c create mode 100644 third-party/mbedtls-3.6/library/x509write_csr.c create mode 100644 third-party/mbedtls-3.6/library/xtea.c create mode 100644 third-party/mbedtls-3.6/makefile create mode 100644 third-party/mbedtls-3.6/mbedtls.kconfig create mode 100644 third-party/mbedtls-3.6/mbedtls_freertos.mk create mode 100644 third-party/mbedtls-3.6/ports/inc/tls_certificate.h create mode 100644 third-party/mbedtls-3.6/ports/inc/tls_net.h create mode 100644 third-party/mbedtls-3.6/ports/src/tls_certificate.c create mode 100644 third-party/mbedtls-3.6/ports/src/tls_net.c create mode 100644 third-party/mbedtls-3.6/src.mk diff --git a/README.md b/README.md index a3d96ba5..2bd91a10 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,21 @@ **v1.1.0** [ReleaseNote](./docs/ChangeLog.md) +**如需Phytium全系CPU的软件适配支持,请联系 ``linan1284@phytium.com.cn``** + +[飞腾腾云S系列高性能服务器CPU](https://www.phytium.com.cn/homepage/production/list/0) + +[飞腾腾锐D系列高效能桌面CPU](https://www.phytium.com.cn/homepage/production/list/1) + +[飞腾腾珑E系列高端嵌入式CPU](https://www.phytium.com.cn/homepage/production/list/2) + ## 1. 介绍 本项目发布了Phytium系列CPU的FreeRTOS源代码,参考例程以及配置构建工具 代码仓库整体共分为两个分支: - master 分支:开发分支,用于保存最新的协作开发代码以及bug修复后的代码。其只要求保障新功能基本正确并且能够满足基本的使用需求,并没有经过系统性和复杂条件下的测试。 -- release 分支:发布分支,包含核心启动代码、芯片外设驱动、用户使用例程和构建的脚本工具。用于保存经过系统性测试的代码并对外发布版本,默认下载此分支的代码。 +- release 分支:发布分支,包含核心启动代码、芯片外设驱动、用户使用例程和构建的脚本工具。用于保存经过系统性测试的代码并对外发布版本。 --- diff --git a/docs/ChangeLog.md b/docs/ChangeLog.md index 88fb9b4b..6c31897e 100644 --- a/docs/ChangeLog.md +++ b/docs/ChangeLog.md @@ -1,3 +1,61 @@ +# Phytium FreeRTOS SDK 2025-01-20 ChangeLog + +Change Log since 2025-01-15 + +## example + +- Change the media example to support new media driver + +## driver + +- Change the media example to support new sdk media driver + +- Change the gmac driver to support sdk gitee + +# Phytium FreeRTOS SDK 2025-01-15 ChangeLog + +Change Log since 2025-01-14 + +## example + +- Refine dhcp and qspi examples + +## third-party + +- Add prvTaskExitError() function in aarch64 port + +# Phytium FreeRTOS SDK 2024-12-03 ChangeLog + +Change Log since 2024-10-15 + +## example + +- Modify the openamp example to support MSDF(multi-core system deployment framework) + +# Phytium FreeRTOS SDK 2024-10-15 ChangeLog + +Change Log since 2024-10-15 + +## third-party + +- Add polled letter-shell config + +## third-party + +- Add virtual timer as FreeRtos tick interrupt source + +# Phytium FreeRTOS SDK 2024-10-15 ChangeLog + +Change Log since 2024-10-15 + +## example + +- Add an https test + +## third-party + +- Add mbedtls encryption library + # Phytium FreeRTOS SDK 2024-10-15 v1.1.0 ChangeLog Change Log since 2024-10-12 diff --git a/drivers/eth/gmac/fgmac_os.c b/drivers/eth/gmac/fgmac_os.c index 7eb95597..f392f9b4 100644 --- a/drivers/eth/gmac/fgmac_os.c +++ b/drivers/eth/gmac/fgmac_os.c @@ -339,7 +339,7 @@ FError FGmacOsInit(FGmacOs *instance_p) } /* Initialize Rx Description list : ring Mode */ - status = FGmacSetupRxDescRing(gmac_p, (FGmacDmaDesc *)(instance_p->rx_desc), instance_p->rx_buf, FGMAC_MAX_PACKET_SIZE, GMAC_RX_DESCNUM); + status = FGmacSetupRxDescRing(gmac_p, (FGmacDmaDesc *)(instance_p->rx_desc), (uintptr)(instance_p->rx_desc), instance_p->rx_buf, (uintptr)(instance_p->rx_buf), FGMAC_MAX_PACKET_SIZE, GMAC_RX_DESCNUM); if (FT_SUCCESS != status) { OS_MAC_DEBUG_E("Gmac setup rx return err code %d", status); @@ -347,7 +347,7 @@ FError FGmacOsInit(FGmacOs *instance_p) } /* Initialize Tx Description list : ring Mode */ - status = FGmacSetupTxDescRing(gmac_p, (FGmacDmaDesc *)(instance_p->tx_desc), instance_p->tx_buf, FGMAC_MAX_PACKET_SIZE, GMAC_TX_DESCNUM); + status = FGmacSetupTxDescRing(gmac_p, (FGmacDmaDesc *)(instance_p->tx_desc), (uintptr)(instance_p->tx_desc), instance_p->tx_buf, (uintptr)(instance_p->tx_buf), FGMAC_MAX_PACKET_SIZE, GMAC_TX_DESCNUM); if (FT_SUCCESS != status) { OS_MAC_DEBUG_E("Gmac setup tx return err code %d", status); diff --git a/drivers/eth/xmac/fxmac_os.c b/drivers/eth/xmac/fxmac_os.c index c2420349..132a9764 100644 --- a/drivers/eth/xmac/fxmac_os.c +++ b/drivers/eth/xmac/fxmac_os.c @@ -25,6 +25,7 @@ #include "fparameters.h" #include "fassert.h" #include "fxmac_os.h" +#include "fxmac_phy.h" #include "fxmac.h" #include "fcache.h" #include "fxmac_bdring.h" diff --git a/drivers/media/fmedia_os.c b/drivers/media/fmedia_os.c index 8b801997..ff8848b6 100644 --- a/drivers/media/fmedia_os.c +++ b/drivers/media/fmedia_os.c @@ -32,7 +32,6 @@ #include "fdcdp.h" #include "fdp_hw.h" #include "fdp.h" -#include "fdc_common_hw.h" /***************** Macros (Inline Functions) Definitions *********************/ @@ -47,32 +46,24 @@ * @name: FFreeRTOSMediaHwInit * @msg: init the media,dc and dp * @param {u32} channel is the dc channel + * @param {FFreeRTOSMedia*} instance is the driver instance * @param {u32} width is the width * @param {u32} height is the height - * @param {u32} multi_mode is multi display mode,0:clone,1:hor,2:ver - * @param {u32} color_depth is the color depth - * @param {u32} refresh_rate is the refresh rate of screen * @return err code information, 0 indicates success,others indicates failed */ -FFreeRTOSMedia *FFreeRTOSMediaHwInit(u32 channel,FFreeRTOSMedia *instance) +FFreeRTOSMedia *FFreeRTOSMediaHwInit(FFreeRTOSMedia *instance, u32 width, u32 height) { FError ret = FT_SUCCESS; u32 index; - FDcDpCfgInitialize(&instance->dcdp_ctrl); for (index = 0; index < FDCDP_INSTANCE_NUM; index ++) { - instance->dcdp_ctrl.dc_instance_p[index].config = *FDcLookupConfig(index); - instance->dcdp_ctrl.dp_instance_p[index].config = *FDpLookupConfig(index); + ret = FDcDpInitial(&instance->dcdp_ctrl, index, width, height); } - ret = FDcDpInitialize(&instance->dcdp_ctrl, channel); - if (ret != FMEDIA_DP_SUCCESS) + if((instance->dcdp_ctrl.is_initialized[0]) | (instance->dcdp_ctrl.is_initialized[1])) { - FMEDIA_ERROR("DcDp initial failed"); - goto err_exit; + ret = FDP_SUCCESS; } - -err_exit: return (FT_SUCCESS == ret) ? instance : NULL; /* exit with NULL if failed */ } diff --git a/drivers/media/fmedia_os.h b/drivers/media/fmedia_os.h index fa1e8165..d70115ec 100644 --- a/drivers/media/fmedia_os.h +++ b/drivers/media/fmedia_os.h @@ -48,7 +48,7 @@ typedef struct } FFreeRTOSMedia; /*init the media and return the meidia instance*/ -FFreeRTOSMedia *FFreeRTOSMediaHwInit(u32 channel,FFreeRTOSMedia *instance); +FFreeRTOSMedia *FFreeRTOSMediaHwInit(FFreeRTOSMedia *instance, u32 width, u32 height); #ifdef __cplusplus diff --git a/example/freertos_feature/eventgroup/configs/d2000_aarch32_test_eventgroup.config b/example/freertos_feature/eventgroup/configs/d2000_aarch32_test_eventgroup.config index ddbc8c4f..4d7aa1e9 100644 --- a/example/freertos_feature/eventgroup/configs/d2000_aarch32_test_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/d2000_aarch32_test_eventgroup.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/d2000_aarch64_test_eventgroup.config b/example/freertos_feature/eventgroup/configs/d2000_aarch64_test_eventgroup.config index 1e979599..c0419832 100644 --- a/example/freertos_feature/eventgroup/configs/d2000_aarch64_test_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/d2000_aarch64_test_eventgroup.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/e2000d_aarch32_demo_eventgroup.config b/example/freertos_feature/eventgroup/configs/e2000d_aarch32_demo_eventgroup.config index 36ec22a7..65fff9a5 100644 --- a/example/freertos_feature/eventgroup/configs/e2000d_aarch32_demo_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/e2000d_aarch32_demo_eventgroup.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/e2000d_aarch64_demo_eventgroup.config b/example/freertos_feature/eventgroup/configs/e2000d_aarch64_demo_eventgroup.config index ed089464..1e1aa9ff 100644 --- a/example/freertos_feature/eventgroup/configs/e2000d_aarch64_demo_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/e2000d_aarch64_demo_eventgroup.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/e2000q_aarch32_demo_eventgroup.config b/example/freertos_feature/eventgroup/configs/e2000q_aarch32_demo_eventgroup.config index a0ee85b6..bfd63965 100644 --- a/example/freertos_feature/eventgroup/configs/e2000q_aarch32_demo_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/e2000q_aarch32_demo_eventgroup.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/e2000q_aarch64_demo_eventgroup.config b/example/freertos_feature/eventgroup/configs/e2000q_aarch64_demo_eventgroup.config index 5c1ddf31..a0ab76c7 100644 --- a/example/freertos_feature/eventgroup/configs/e2000q_aarch64_demo_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/e2000q_aarch64_demo_eventgroup.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/ft2004_aarch32_dsk_eventgroup.config b/example/freertos_feature/eventgroup/configs/ft2004_aarch32_dsk_eventgroup.config index 707209d9..25a06495 100644 --- a/example/freertos_feature/eventgroup/configs/ft2004_aarch32_dsk_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/ft2004_aarch32_dsk_eventgroup.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/ft2004_aarch64_dsk_eventgroup.config b/example/freertos_feature/eventgroup/configs/ft2004_aarch64_dsk_eventgroup.config index 8f66c8a8..2dcb55e6 100644 --- a/example/freertos_feature/eventgroup/configs/ft2004_aarch64_dsk_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/ft2004_aarch64_dsk_eventgroup.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/phytiumpi_aarch32_firefly_eventgroup.config b/example/freertos_feature/eventgroup/configs/phytiumpi_aarch32_firefly_eventgroup.config index b77b6348..5e3fc363 100644 --- a/example/freertos_feature/eventgroup/configs/phytiumpi_aarch32_firefly_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/phytiumpi_aarch32_firefly_eventgroup.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -95,6 +96,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -321,6 +326,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/configs/phytiumpi_aarch64_firefly_eventgroup.config b/example/freertos_feature/eventgroup/configs/phytiumpi_aarch64_firefly_eventgroup.config index 29126d74..20a67624 100644 --- a/example/freertos_feature/eventgroup/configs/phytiumpi_aarch64_firefly_eventgroup.config +++ b/example/freertos_feature/eventgroup/configs/phytiumpi_aarch64_firefly_eventgroup.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -89,6 +90,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -279,6 +281,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -288,6 +291,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -310,6 +315,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/sdkconfig b/example/freertos_feature/eventgroup/sdkconfig index 29126d74..20a67624 100644 --- a/example/freertos_feature/eventgroup/sdkconfig +++ b/example/freertos_feature/eventgroup/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -89,6 +90,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -279,6 +281,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -288,6 +291,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -310,6 +315,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/eventgroup/sdkconfig.h b/example/freertos_feature/eventgroup/sdkconfig.h index cdc7fa45..43aff328 100644 --- a/example/freertos_feature/eventgroup/sdkconfig.h +++ b/example/freertos_feature/eventgroup/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -83,6 +84,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -247,6 +249,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -255,6 +258,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -275,6 +280,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/freertos_feature/interrupt/configs/d2000_aarch32_test_interrupt.config b/example/freertos_feature/interrupt/configs/d2000_aarch32_test_interrupt.config index 54a6d759..a4d21793 100644 --- a/example/freertos_feature/interrupt/configs/d2000_aarch32_test_interrupt.config +++ b/example/freertos_feature/interrupt/configs/d2000_aarch32_test_interrupt.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/d2000_aarch64_test_interrupt.config b/example/freertos_feature/interrupt/configs/d2000_aarch64_test_interrupt.config index 572d6135..b332ca91 100644 --- a/example/freertos_feature/interrupt/configs/d2000_aarch64_test_interrupt.config +++ b/example/freertos_feature/interrupt/configs/d2000_aarch64_test_interrupt.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/e2000d_aarch32_demo_interrupt.config b/example/freertos_feature/interrupt/configs/e2000d_aarch32_demo_interrupt.config index 8efa6b27..81f1bc3c 100644 --- a/example/freertos_feature/interrupt/configs/e2000d_aarch32_demo_interrupt.config +++ b/example/freertos_feature/interrupt/configs/e2000d_aarch32_demo_interrupt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/e2000d_aarch64_demo_interrupt.config b/example/freertos_feature/interrupt/configs/e2000d_aarch64_demo_interrupt.config index 7a351643..3d5dc006 100644 --- a/example/freertos_feature/interrupt/configs/e2000d_aarch64_demo_interrupt.config +++ b/example/freertos_feature/interrupt/configs/e2000d_aarch64_demo_interrupt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/e2000q_aarch32_demo_interrupt.config b/example/freertos_feature/interrupt/configs/e2000q_aarch32_demo_interrupt.config index c9b7f64b..9dcb569e 100644 --- a/example/freertos_feature/interrupt/configs/e2000q_aarch32_demo_interrupt.config +++ b/example/freertos_feature/interrupt/configs/e2000q_aarch32_demo_interrupt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/e2000q_aarch64_demo_interrupt.config b/example/freertos_feature/interrupt/configs/e2000q_aarch64_demo_interrupt.config index 655538d2..b6fbc624 100644 --- a/example/freertos_feature/interrupt/configs/e2000q_aarch64_demo_interrupt.config +++ b/example/freertos_feature/interrupt/configs/e2000q_aarch64_demo_interrupt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/ft2004_aarch32_dsk_interrupt.config b/example/freertos_feature/interrupt/configs/ft2004_aarch32_dsk_interrupt.config index 4eaa1e5e..ad490326 100644 --- a/example/freertos_feature/interrupt/configs/ft2004_aarch32_dsk_interrupt.config +++ b/example/freertos_feature/interrupt/configs/ft2004_aarch32_dsk_interrupt.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/ft2004_aarch64_dsk_interrupt.config b/example/freertos_feature/interrupt/configs/ft2004_aarch64_dsk_interrupt.config index 0080b72c..31bc7adf 100644 --- a/example/freertos_feature/interrupt/configs/ft2004_aarch64_dsk_interrupt.config +++ b/example/freertos_feature/interrupt/configs/ft2004_aarch64_dsk_interrupt.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/phytiumpi_aarch32_firefly_interrupt.config b/example/freertos_feature/interrupt/configs/phytiumpi_aarch32_firefly_interrupt.config index f828ffe7..989c6473 100644 --- a/example/freertos_feature/interrupt/configs/phytiumpi_aarch32_firefly_interrupt.config +++ b/example/freertos_feature/interrupt/configs/phytiumpi_aarch32_firefly_interrupt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/configs/phytiumpi_aarch64_firefly_interrupt.config b/example/freertos_feature/interrupt/configs/phytiumpi_aarch64_firefly_interrupt.config index 0adf13c0..c7f44459 100644 --- a/example/freertos_feature/interrupt/configs/phytiumpi_aarch64_firefly_interrupt.config +++ b/example/freertos_feature/interrupt/configs/phytiumpi_aarch64_firefly_interrupt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/sdkconfig b/example/freertos_feature/interrupt/sdkconfig index 0adf13c0..c7f44459 100644 --- a/example/freertos_feature/interrupt/sdkconfig +++ b/example/freertos_feature/interrupt/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/interrupt/sdkconfig.h b/example/freertos_feature/interrupt/sdkconfig.h index 43acfeb0..48484cfd 100644 --- a/example/freertos_feature/interrupt/sdkconfig.h +++ b/example/freertos_feature/interrupt/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/freertos_feature/queue/configs/d2000_aarch32_test_queue.config b/example/freertos_feature/queue/configs/d2000_aarch32_test_queue.config index 5831753b..ec921027 100644 --- a/example/freertos_feature/queue/configs/d2000_aarch32_test_queue.config +++ b/example/freertos_feature/queue/configs/d2000_aarch32_test_queue.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/d2000_aarch64_test_queue.config b/example/freertos_feature/queue/configs/d2000_aarch64_test_queue.config index 05fa24b7..62273286 100644 --- a/example/freertos_feature/queue/configs/d2000_aarch64_test_queue.config +++ b/example/freertos_feature/queue/configs/d2000_aarch64_test_queue.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/e2000d_aarch32_demo_queue.config b/example/freertos_feature/queue/configs/e2000d_aarch32_demo_queue.config index c14faba9..bdb5c5b9 100644 --- a/example/freertos_feature/queue/configs/e2000d_aarch32_demo_queue.config +++ b/example/freertos_feature/queue/configs/e2000d_aarch32_demo_queue.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/e2000d_aarch64_demo_queue.config b/example/freertos_feature/queue/configs/e2000d_aarch64_demo_queue.config index 75d88d07..c48adf26 100644 --- a/example/freertos_feature/queue/configs/e2000d_aarch64_demo_queue.config +++ b/example/freertos_feature/queue/configs/e2000d_aarch64_demo_queue.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/e2000q_aarch32_demo_queue.config b/example/freertos_feature/queue/configs/e2000q_aarch32_demo_queue.config index 14e83f3f..fe37d918 100644 --- a/example/freertos_feature/queue/configs/e2000q_aarch32_demo_queue.config +++ b/example/freertos_feature/queue/configs/e2000q_aarch32_demo_queue.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/e2000q_aarch64_demo_queue.config b/example/freertos_feature/queue/configs/e2000q_aarch64_demo_queue.config index 296be302..e238d0a3 100644 --- a/example/freertos_feature/queue/configs/e2000q_aarch64_demo_queue.config +++ b/example/freertos_feature/queue/configs/e2000q_aarch64_demo_queue.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/ft2004_aarch32_dsk_queue.config b/example/freertos_feature/queue/configs/ft2004_aarch32_dsk_queue.config index c9db9e65..217fa7b8 100644 --- a/example/freertos_feature/queue/configs/ft2004_aarch32_dsk_queue.config +++ b/example/freertos_feature/queue/configs/ft2004_aarch32_dsk_queue.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/ft2004_aarch64_dsk_queue.config b/example/freertos_feature/queue/configs/ft2004_aarch64_dsk_queue.config index 92697740..a082de99 100644 --- a/example/freertos_feature/queue/configs/ft2004_aarch64_dsk_queue.config +++ b/example/freertos_feature/queue/configs/ft2004_aarch64_dsk_queue.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/phytiumpi_aarch32_firefly_queue.config b/example/freertos_feature/queue/configs/phytiumpi_aarch32_firefly_queue.config index 55fb5135..312ee508 100644 --- a/example/freertos_feature/queue/configs/phytiumpi_aarch32_firefly_queue.config +++ b/example/freertos_feature/queue/configs/phytiumpi_aarch32_firefly_queue.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/configs/phytiumpi_aarch64_firefly_queue.config b/example/freertos_feature/queue/configs/phytiumpi_aarch64_firefly_queue.config index 804de2d0..79ec01e3 100644 --- a/example/freertos_feature/queue/configs/phytiumpi_aarch64_firefly_queue.config +++ b/example/freertos_feature/queue/configs/phytiumpi_aarch64_firefly_queue.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/sdkconfig b/example/freertos_feature/queue/sdkconfig index 804de2d0..79ec01e3 100644 --- a/example/freertos_feature/queue/sdkconfig +++ b/example/freertos_feature/queue/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/queue/sdkconfig.h b/example/freertos_feature/queue/sdkconfig.h index 12b86c67..37aa65b7 100644 --- a/example/freertos_feature/queue/sdkconfig.h +++ b/example/freertos_feature/queue/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/freertos_feature/resource/configs/d2000_aarch32_test_resoure.config b/example/freertos_feature/resource/configs/d2000_aarch32_test_resoure.config index f393b868..dd22c2c3 100644 --- a/example/freertos_feature/resource/configs/d2000_aarch32_test_resoure.config +++ b/example/freertos_feature/resource/configs/d2000_aarch32_test_resoure.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/d2000_aarch64_test_resoure.config b/example/freertos_feature/resource/configs/d2000_aarch64_test_resoure.config index 1ee78324..bb8a8d8b 100644 --- a/example/freertos_feature/resource/configs/d2000_aarch64_test_resoure.config +++ b/example/freertos_feature/resource/configs/d2000_aarch64_test_resoure.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/e2000d_aarch32_demo_resoure.config b/example/freertos_feature/resource/configs/e2000d_aarch32_demo_resoure.config index 1b67bc96..c5b50c1a 100644 --- a/example/freertos_feature/resource/configs/e2000d_aarch32_demo_resoure.config +++ b/example/freertos_feature/resource/configs/e2000d_aarch32_demo_resoure.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/e2000d_aarch64_demo_resoure.config b/example/freertos_feature/resource/configs/e2000d_aarch64_demo_resoure.config index 3d30e301..b65da87e 100644 --- a/example/freertos_feature/resource/configs/e2000d_aarch64_demo_resoure.config +++ b/example/freertos_feature/resource/configs/e2000d_aarch64_demo_resoure.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/e2000q_aarch32_demo_resoure.config b/example/freertos_feature/resource/configs/e2000q_aarch32_demo_resoure.config index dc1e0b77..705f05e2 100644 --- a/example/freertos_feature/resource/configs/e2000q_aarch32_demo_resoure.config +++ b/example/freertos_feature/resource/configs/e2000q_aarch32_demo_resoure.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/e2000q_aarch64_demo_resoure.config b/example/freertos_feature/resource/configs/e2000q_aarch64_demo_resoure.config index 03e9adbe..5f911cc5 100644 --- a/example/freertos_feature/resource/configs/e2000q_aarch64_demo_resoure.config +++ b/example/freertos_feature/resource/configs/e2000q_aarch64_demo_resoure.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/ft2004_aarch32_dsk_resoure.config b/example/freertos_feature/resource/configs/ft2004_aarch32_dsk_resoure.config index c378fd3f..c82d7e2b 100644 --- a/example/freertos_feature/resource/configs/ft2004_aarch32_dsk_resoure.config +++ b/example/freertos_feature/resource/configs/ft2004_aarch32_dsk_resoure.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/ft2004_aarch64_dsk_resoure.config b/example/freertos_feature/resource/configs/ft2004_aarch64_dsk_resoure.config index 195394a5..4daf60b4 100644 --- a/example/freertos_feature/resource/configs/ft2004_aarch64_dsk_resoure.config +++ b/example/freertos_feature/resource/configs/ft2004_aarch64_dsk_resoure.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/phytiumpi_aarch32_firefly_resoure.config b/example/freertos_feature/resource/configs/phytiumpi_aarch32_firefly_resoure.config index bbc779d0..3bf02446 100644 --- a/example/freertos_feature/resource/configs/phytiumpi_aarch32_firefly_resoure.config +++ b/example/freertos_feature/resource/configs/phytiumpi_aarch32_firefly_resoure.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/configs/phytiumpi_aarch64_firefly_resoure.config b/example/freertos_feature/resource/configs/phytiumpi_aarch64_firefly_resoure.config index 6ef610d9..1de70412 100644 --- a/example/freertos_feature/resource/configs/phytiumpi_aarch64_firefly_resoure.config +++ b/example/freertos_feature/resource/configs/phytiumpi_aarch64_firefly_resoure.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/sdkconfig b/example/freertos_feature/resource/sdkconfig index 6ef610d9..1de70412 100644 --- a/example/freertos_feature/resource/sdkconfig +++ b/example/freertos_feature/resource/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/resource/sdkconfig.h b/example/freertos_feature/resource/sdkconfig.h index a0b66d17..24f78c45 100644 --- a/example/freertos_feature/resource/sdkconfig.h +++ b/example/freertos_feature/resource/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/freertos_feature/software_timer/README.md b/example/freertos_feature/software_timer/README.md index 59dce8cf..882eb7c5 100644 --- a/example/freertos_feature/software_timer/README.md +++ b/example/freertos_feature/software_timer/README.md @@ -42,6 +42,9 @@ FreeRTOS 提供的软件定时器支持单次模式和周期模式; - CONFIG_USE_LETTER_SHELL +- CONFIG_NON_SECURE_PHYSICAL_TIMER 或 CONFIG_NON_SECURE_VIRTUAL_TIMER 选择使用非安全物理定时器或者虚拟定时器作为Tick中断源 +![tick_interrupt_source_config](./figs/tick_interrupt_source_config.png) + 本例子已经提供好具体的编译指令,以下进行介绍: - make 将目录下的工程进行编译 - make clean 将目录下的工程进行清理 diff --git a/example/freertos_feature/software_timer/configs/d2000_aarch32_test_software_timer.config b/example/freertos_feature/software_timer/configs/d2000_aarch32_test_software_timer.config index 81d62a6f..1b432716 100644 --- a/example/freertos_feature/software_timer/configs/d2000_aarch32_test_software_timer.config +++ b/example/freertos_feature/software_timer/configs/d2000_aarch32_test_software_timer.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/d2000_aarch64_test_software_timer.config b/example/freertos_feature/software_timer/configs/d2000_aarch64_test_software_timer.config index 249e75b6..bd90f95b 100644 --- a/example/freertos_feature/software_timer/configs/d2000_aarch64_test_software_timer.config +++ b/example/freertos_feature/software_timer/configs/d2000_aarch64_test_software_timer.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/e2000d_aarch32_demo_software_timer.config b/example/freertos_feature/software_timer/configs/e2000d_aarch32_demo_software_timer.config index 3e736184..442d426f 100644 --- a/example/freertos_feature/software_timer/configs/e2000d_aarch32_demo_software_timer.config +++ b/example/freertos_feature/software_timer/configs/e2000d_aarch32_demo_software_timer.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/e2000d_aarch64_demo_software_timer.config b/example/freertos_feature/software_timer/configs/e2000d_aarch64_demo_software_timer.config index 431241b0..8a7ad6ca 100644 --- a/example/freertos_feature/software_timer/configs/e2000d_aarch64_demo_software_timer.config +++ b/example/freertos_feature/software_timer/configs/e2000d_aarch64_demo_software_timer.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/e2000q_aarch32_demo_software_timer.config b/example/freertos_feature/software_timer/configs/e2000q_aarch32_demo_software_timer.config index 3c35d420..9ba33418 100644 --- a/example/freertos_feature/software_timer/configs/e2000q_aarch32_demo_software_timer.config +++ b/example/freertos_feature/software_timer/configs/e2000q_aarch32_demo_software_timer.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/e2000q_aarch64_demo_software_timer.config b/example/freertos_feature/software_timer/configs/e2000q_aarch64_demo_software_timer.config index 7e651cb9..38b3d982 100644 --- a/example/freertos_feature/software_timer/configs/e2000q_aarch64_demo_software_timer.config +++ b/example/freertos_feature/software_timer/configs/e2000q_aarch64_demo_software_timer.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/ft2004_aarch32_dsk_software_timer.config b/example/freertos_feature/software_timer/configs/ft2004_aarch32_dsk_software_timer.config index aa975b7c..fa4a0e64 100644 --- a/example/freertos_feature/software_timer/configs/ft2004_aarch32_dsk_software_timer.config +++ b/example/freertos_feature/software_timer/configs/ft2004_aarch32_dsk_software_timer.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/ft2004_aarch64_dsk_software_timer.config b/example/freertos_feature/software_timer/configs/ft2004_aarch64_dsk_software_timer.config index 2bca5361..fd19cdc8 100644 --- a/example/freertos_feature/software_timer/configs/ft2004_aarch64_dsk_software_timer.config +++ b/example/freertos_feature/software_timer/configs/ft2004_aarch64_dsk_software_timer.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/phytiumpi_aarch32_firefly_software_timer.config b/example/freertos_feature/software_timer/configs/phytiumpi_aarch32_firefly_software_timer.config index f62ed805..3a9c9b71 100644 --- a/example/freertos_feature/software_timer/configs/phytiumpi_aarch32_firefly_software_timer.config +++ b/example/freertos_feature/software_timer/configs/phytiumpi_aarch32_firefly_software_timer.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/configs/phytiumpi_aarch64_firefly_software_timer.config b/example/freertos_feature/software_timer/configs/phytiumpi_aarch64_firefly_software_timer.config index b9835fcb..98e28cda 100644 --- a/example/freertos_feature/software_timer/configs/phytiumpi_aarch64_firefly_software_timer.config +++ b/example/freertos_feature/software_timer/configs/phytiumpi_aarch64_firefly_software_timer.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/freertos_feature/software_timer/figs/tick_interrupt_source_config.png b/example/freertos_feature/software_timer/figs/tick_interrupt_source_config.png new file mode 100644 index 0000000000000000000000000000000000000000..cdce90547050a6ba17e6d8b482df5123d118718b GIT binary patch literal 13001 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介绍例程的用途,使用场景,相关基本概念,描述用户可以使用例程完成哪些工作
+ +本例程示范了一个简单的Https client,与测试网站建立TLS连接并获取加密数据。 + +### 1.1 Https client测试例程 (https_example.c) +- ipv4模式下初始化开发板上所有网口以及对应网卡控制器 +- 为每个网卡配置静态IPv4地址 +- client连接主机TLS测试网站 +- client和server握手成功 +- client发送请求 +- server回应请求 + +## 2. 如何使用例程 + +>描述开发平台准备,使用例程配置,构建和下载镜像的过程
+ +本例程需要以下硬件, + +- E2000D/Q Demo板,FT2000/4开发板,D2000开发板,PhytiumPi +- 串口线和串口上位机 + +### 2.1 硬件配置方法 + +>哪些硬件平台是支持的,需要哪些外设,例程与开发板哪些IO口相关等(建议附录开发板照片,展示哪些IO口被引出)
+- 为方便测试,一般需要自带路由器设备。 +- 利用路由器上的多个接口,我们可以更加方便的进行多网口测试。 +- 路由器一般能够提供dhcp服务,利用该服务,我们可以在运行网卡dhcp模式初始化测试例程时看到相应的dhcp服务器分配地址的现象。 +- 关于路由器配置,请参考网上相关资料自行配置。 + +### 2.2 SDK配置方法 + +>依赖哪些驱动、库和第三方组件,如何完成配置(列出需要使能的关键配置项)
+ +本例程需要: +- LWIP组件,依赖 USE_LWIP +- Letter Shell组件,依赖 USE_LETTER_SHELL +- MBEDTLS组件,依赖 USE_MBEDTLS + +对应的配置项是, + +- CONFIG_USE_LWIP +- CONFIG_USE_LETTER_SHELL +- CONFIG_USE_MBEDTLS + +- 本例子已经提供好具体的编译指令,以下进行介绍: + + 1. make 将目录下的工程进行编译 + 2. make clean 将目录下的工程进行清理 + 3. make image 将目录下的工程进行编译,并将生成的elf 复制到目标地址 + 4. make list_kconfig 当前工程支持哪些配置文件 + 5. make load_kconfig LOAD_CONFIG_NAME=`` 将预设配置加载至工程中 + 6. make menuconfig 配置目录下的参数变量 + 7. make backup_kconfig 将目录下的sdkconfig 备份到./configs下 +- 具体使用方法为: + + - 在当前目录下 + - 执行以上指令 + +### 2.3 构建和下载 + +>描述构建、烧录下载镜像的过程,列出相关的命令
+ +本文档将以E2000D demo开发板为例,对于其它平台,使用对应的默认配置 + +- 在host端完成配置 +- 选择目标平台 + +``` +make load_kconfig LOAD_CONFIG_NAME=e2000d_aarch64_demo_lwip_https +``` + +- 选择例程需要的配置 + +``` +make menuconfig +``` + +- 进行编译 + +``` +make +``` + +- 将编译出的镜像放置到tftp目录下 + +``` +make image +``` + +- host侧设置重启host侧tftp服务器 + +``` +sudo service tftpd-hpa restart +``` + +- 开发板侧使用bootelf命令跳转 + +``` +setenv ipaddr 192.168.4.20 +setenv serverip 192.168.4.50 +setenv gatewayip 192.168.4.1 +tftpboot 0x90100000 freertos.elf +bootelf -p 0x90100000 +``` + +### 2.4 输出与实验现象 + +>描述输入输出情况,列出存在哪些输出,对应的输出是什么(建议附录相关现象图片)
+ +#### 2.4.1 Https client测试例程 (https_example.c) + +首先在主机端tools目录下启动https服务器 + +![https_server](./fig/https_server.png) + +然后在开发板端启动https客户端,并连接到测试网站 +``` +lwip https +``` + +![https_client](./fig/https_client.png) + + +## 3. 如何解决问题 + +- Q: 如何静态配置开发板的ip地址? +- A: ipv4地址在board_mac_config静态变量中修改如下成员变量即可: + +``` + .ipaddr="192.168.4.10", + .gw="192.168.4.1", + .netmask="255.255.255.0", +``` + +- A: ipv6地址在board_mac_config静态变量中修改如下成员变量即可: + +``` + .mac_address={0x98, 0x0e, 0x24, 0x00, 0x11, 0x1}, +``` + +## 4. 修改历史记录 diff --git a/example/network/lwip_https/configs/d2000_aarch32_test_lwip_https.config b/example/network/lwip_https/configs/d2000_aarch32_test_lwip_https.config new file mode 100644 index 00000000..6edc5b32 --- /dev/null +++ b/example/network/lwip_https/configs/d2000_aarch32_test_lwip_https.config @@ -0,0 +1,606 @@ +CONFIG_USE_FREERTOS=y + +# +# Arch configuration +# +CONFIG_TARGET_ARMv8=y +CONFIG_ARCH_NAME="armv8" + +# +# Arm architecture configuration +# +# CONFIG_ARCH_ARMV8_AARCH64 is not set +CONFIG_ARCH_ARMV8_AARCH32=y + +# +# Compiler configuration +# +CONFIG_ARM_GCC_SELECT=y +# CONFIG_ARM_CLANG_SELECT is not set +CONFIG_TOOLCHAIN_NAME="gcc" +CONFIG_TARGET_ARMV8_AARCH32=y +CONFIG_ARCH_EXECUTION_STATE="aarch32" + +# +# Fpu configuration +# +CONFIG_CRYPTO_NEON_FP_ARMV8=y +# CONFIG_VFPV4 is not set +# CONFIG_VFPV4_D16 is not set +# CONFIG_VFPV3 is not set +# CONFIG_VFPV3_D16 is not set +CONFIG_ARM_MFPU="crypto-neon-fp-armv8" +CONFIG_MFLOAT_ABI_HARD=y +# CONFIG_MFLOAT_ABI_SOFTFP is not set +CONFIG_ARM_MFLOAT_ABI="hard" +# end of Fpu configuration +# end of Compiler configuration + +# CONFIG_USE_L3CACHE is not set +CONFIG_USE_AARCH64_L1_TO_AARCH32=y +# end of Arm architecture configuration + +CONFIG_MMU_PAGE_SIZE=0x1000 +CONFIG_FMMU_NUM_L2_TABLES=256 +# end of Arch configuration + +# +# Soc configuration +# +# CONFIG_TARGET_PHYTIUMPI is not set +# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_E2000D is not set +# CONFIG_TARGET_E2000S is not set +# CONFIG_TARGET_FT2004 is not set +CONFIG_TARGET_D2000=y +# CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="d2000" +CONFIG_SOC_CORE_NUM=8 +CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 +CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 +CONFIG_F64BIT_MEMORY_ADDRESS=0x2000000000 +CONFIG_F64BIT_MEMORY_LENGTH=0x800000000 +CONFIG_DEFAULT_DEBUG_PRINT_UART1=y +# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set +# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set +# end of Soc configuration + +# +# Board Configuration +# +CONFIG_BOARD_NAME="test" +CONFIG_D2000_TEST_BOARD=y + +# +# IO mux configuration when board start up +# +# CONFIG_CUS_DEMO_BOARD is not set + +# +# Build project name +# +CONFIG_TARGET_NAME="lwip_https" +# end of Build project name +# end of Board Configuration + +# +# Sdk common configuration +# +CONFIG_ELOG_LINE_BUF_SIZE=0x100 +# CONFIG_LOG_VERBOS is not set +# CONFIG_LOG_DEBUG is not set +# CONFIG_LOG_INFO is not set +# CONFIG_LOG_WARN is not set +CONFIG_LOG_ERROR=y +# CONFIG_LOG_NONE is not set +# CONFIG_LOG_EXTRA_INFO is not set +# CONFIG_LOG_DISPALY_CORE_NUM is not set +# CONFIG_BOOTUP_DEBUG_PRINTS is not set +CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y +CONFIG_INTERRUPT_ROLE_MASTER=y +# CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set +# end of Sdk common configuration + +# +# Drivers configuration +# +CONFIG_USE_IOMUX=y +CONFIG_ENABLE_IOCTRL=y +# CONFIG_ENABLE_IOPAD is not set +# CONFIG_USE_SPI is not set +# CONFIG_USE_QSPI is not set +CONFIG_USE_SERIAL=y + +# +# Usart Configuration +# +CONFIG_ENABLE_Pl011_UART=y +# end of Usart Configuration + +# CONFIG_USE_GPIO is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +# CONFIG_ENABLE_FXMAC is not set +CONFIG_ENABLE_FGMAC=y +CONFIG_FGMAC_PHY_COMMON=y +# CONFIG_FGMAC_PHY_AR803X is not set +# end of Eth Configuration + +# CONFIG_USE_CAN is not set +# CONFIG_USE_I2C is not set +# CONFIG_USE_TIMER is not set +# CONFIG_USE_MIO is not set +# CONFIG_USE_SDMMC is not set +# CONFIG_USE_PCIE is not set +# CONFIG_USE_WDT is not set +# CONFIG_USE_DMA is not set +# CONFIG_USE_NAND is not set +# CONFIG_USE_RTC is not set +# CONFIG_USE_SATA is not set +# CONFIG_USE_ADC is not set +# CONFIG_USE_PWM is not set +# CONFIG_USE_IPC is not set +# CONFIG_USE_MEDIA is not set +# CONFIG_USE_SCMI_MHU is not set +# CONFIG_USE_I2S is not set +# CONFIG_USE_I3C is not set +# end of Drivers configuration + +# +# Build setup +# +CONFIG_CHECK_DEPS=y +CONFIG_OUTPUT_BINARY=y + +# +# Optimization options +# +# CONFIG_DEBUG_NOOPT is not set +# CONFIG_DEBUG_CUSTOMOPT is not set +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y +CONFIG_DEBUG_LINK_MAP=y +# CONFIG_CCACHE is not set +# CONFIG_ARCH_COVERAGE is not set +# CONFIG_LTO_FULL is not set +# end of Optimization options + +# +# Debug options +# +# CONFIG_DEBUG_ENABLE_ALL_WARNING is not set +# CONFIG_WALL_WARNING_ERROR is not set +# CONFIG_STRICT_PROTOTYPES is not set +# CONFIG_DEBUG_SYMBOLS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_OUTPUT_ASM_DIS is not set +# CONFIG_ENABLE_WSHADOW is not set +# CONFIG_ENABLE_WUNDEF is not set +CONFIG_DOWNGRADE_DIAG_WARNING=y +# end of Debug options + +# +# Lib +# +CONFIG_USE_COMPILE_CHAIN=y +# CONFIG_USE_NEWLIB is not set +# CONFIG_USE_USER_DEFINED is not set +# end of Lib + +# CONFIG_ENABLE_CXX is not set + +# +# Linker Options +# +CONFIG_DEFAULT_LINKER_SCRIPT=y +# CONFIG_USER_DEFINED_LD is not set +CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 +CONFIG_HEAP_SIZE=1 +CONFIG_SVC_STACK_SIZE=0x1000 +CONFIG_SYS_STACK_SIZE=0x1000 +CONFIG_IRQ_STACK_SIZE=0x1000 +CONFIG_ABORT_STACK_SIZE=0x1000 +CONFIG_FIQ_STACK_SIZE=0x1000 +CONFIG_UNDEF_STACK_SIZE=0x1000 +# end of Linker Options +# end of Build setup + +# +# Component Configuration +# + +# +# Freertos Uart Drivers +# +CONFIG_FREERTOS_USE_UART=y +# end of Freertos Uart Drivers + +# +# Freertos Pwm Drivers +# +# CONFIG_FREERTOS_USE_PWM is not set +# end of Freertos Pwm Drivers + +# +# Freertos Qspi Drivers +# +# CONFIG_FREERTOS_USE_QSPI is not set +# end of Freertos Qspi Drivers + +# +# Freertos Wdt Drivers +# +# CONFIG_FREERTOS_USE_WDT is not set +# end of Freertos Wdt Drivers + +# +# Freertos Eth Drivers +# +# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_GMAC=y +# end of Freertos Eth Drivers + +# +# Freertos Spim Drivers +# +# CONFIG_FREERTOS_USE_FSPIM is not set +# end of Freertos Spim Drivers + +# +# Freertos DMA Drivers +# +# CONFIG_FREERTOS_USE_FDDMA is not set +# CONFIG_FREERTOS_USE_FGDMA is not set +# end of Freertos DMA Drivers + +# +# Freertos Adc Drivers +# +# CONFIG_FREERTOS_USE_ADC is not set +# end of Freertos Adc Drivers + +# +# Freertos Can Drivers +# +# CONFIG_FREERTOS_USE_CAN is not set +# end of Freertos Can Drivers + +# +# Freertos I2c Drivers +# +# CONFIG_FREERTOS_USE_I2C is not set +# end of Freertos I2c Drivers + +# +# Freertos Mio Drivers +# +# CONFIG_FREERTOS_USE_MIO is not set +# end of Freertos Mio Drivers + +# +# Freertos Timer Drivers +# +# CONFIG_FREERTOS_USE_TIMER is not set +# end of Freertos Timer Drivers + +# +# Freertos Media Drivers +# +# CONFIG_FREERTOS_USE_MEDIA is not set +# end of Freertos Media Drivers + +# +# Freertos I2s Drivers +# +# CONFIG_FREERTOS_USE_I2S is not set +# end of Freertos I2s Drivers +# end of Component Configuration + +# +# Third-party configuration +# +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +# CONFIG_LWIP_FXMAC is not set +CONFIG_LWIP_FGMAC=y +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + +# CONFIG_USE_AMP is not set +# CONFIG_USE_YMODEM is not set +# CONFIG_USE_SFUD is not set +CONFIG_USE_BACKTRACE=y +# CONFIG_USE_FATFS_0_1_4 is not set +CONFIG_USE_TLSF=y +# CONFIG_USE_SPIFFS is not set +# CONFIG_USE_LITTLE_FS is not set +# CONFIG_USE_LVGL is not set +# CONFIG_USE_FREEMODBUS is not set +# CONFIG_USE_CHERRY_USB is not set +# CONFIG_USE_FSL_SDMMC is not set +# CONFIG_USE_FSL_WIFI is not set +# end of Third-party configuration + +# +# FreeRTOS Kernel Configuration +# +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set +CONFIG_FREERTOS_MAX_PRIORITIES=32 +CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 +CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_MINIMAL_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=32 +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set +CONFIG_FREERTOS_TOTAL_HEAP_SIZE=10240 +CONFIG_FREERTOS_TASK_FPU_SUPPORT=1 +# CONFIG_FREERTOS_USE_POSIX is not set +# end of FreeRTOS Kernel Configuration diff --git a/example/network/lwip_https/configs/d2000_aarch64_test_lwip_https.config b/example/network/lwip_https/configs/d2000_aarch64_test_lwip_https.config new file mode 100644 index 00000000..ede77f56 --- /dev/null +++ b/example/network/lwip_https/configs/d2000_aarch64_test_lwip_https.config @@ -0,0 +1,595 @@ +CONFIG_USE_FREERTOS=y + +# +# Arch configuration +# +CONFIG_TARGET_ARMv8=y +CONFIG_ARCH_NAME="armv8" + +# +# Arm architecture configuration +# +CONFIG_ARCH_ARMV8_AARCH64=y +# CONFIG_ARCH_ARMV8_AARCH32 is not set + +# +# Compiler configuration +# +CONFIG_ARM_GCC_SELECT=y +# CONFIG_ARM_CLANG_SELECT is not set +CONFIG_TOOLCHAIN_NAME="gcc" +CONFIG_TARGET_ARMV8_AARCH64=y +CONFIG_ARCH_EXECUTION_STATE="aarch64" +CONFIG_ARM_NEON=y +CONFIG_ARM_CRC=y +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_FLOAT_POINT=y +# CONFIG_GCC_CODE_MODEL_TINY is not set +CONFIG_GCC_CODE_MODEL_SMALL=y +# CONFIG_GCC_CODE_MODEL_LARGE is not set +# end of Compiler configuration + +# CONFIG_USE_L3CACHE is not set +# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +# CONFIG_MMU_DEBUG_PRINTS is not set +# end of Arm architecture configuration + +CONFIG_MMU_PAGE_SIZE=0x1000 +CONFIG_MAX_XLAT_TABLES=256 +# end of Arch configuration + +# +# Soc configuration +# +# CONFIG_TARGET_PHYTIUMPI is not set +# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_E2000D is not set +# CONFIG_TARGET_E2000S is not set +# CONFIG_TARGET_FT2004 is not set +CONFIG_TARGET_D2000=y +# CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="d2000" +CONFIG_SOC_CORE_NUM=8 +CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 +CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 +CONFIG_F64BIT_MEMORY_ADDRESS=0x2000000000 +CONFIG_F64BIT_MEMORY_LENGTH=0x800000000 +CONFIG_DEFAULT_DEBUG_PRINT_UART1=y +# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set +# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set +# end of Soc configuration + +# +# Board Configuration +# +CONFIG_BOARD_NAME="test" +CONFIG_D2000_TEST_BOARD=y + +# +# IO mux configuration when board start up +# +# CONFIG_CUS_DEMO_BOARD is not set + +# +# Build project name +# +CONFIG_TARGET_NAME="lwip_https" +# end of Build project name +# end of Board Configuration + +# +# Sdk common configuration +# +CONFIG_ELOG_LINE_BUF_SIZE=0x100 +# CONFIG_LOG_VERBOS is not set +# CONFIG_LOG_DEBUG is not set +# CONFIG_LOG_INFO is not set +# CONFIG_LOG_WARN is not set +CONFIG_LOG_ERROR=y +# CONFIG_LOG_NONE is not set +# CONFIG_LOG_EXTRA_INFO is not set +# CONFIG_LOG_DISPALY_CORE_NUM is not set +# CONFIG_BOOTUP_DEBUG_PRINTS is not set +CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y +CONFIG_INTERRUPT_ROLE_MASTER=y +# CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set +# end of Sdk common configuration + +# +# Drivers configuration +# +CONFIG_USE_IOMUX=y +CONFIG_ENABLE_IOCTRL=y +# CONFIG_ENABLE_IOPAD is not set +# CONFIG_USE_SPI is not set +# CONFIG_USE_QSPI is not set +CONFIG_USE_SERIAL=y + +# +# Usart Configuration +# +CONFIG_ENABLE_Pl011_UART=y +# end of Usart Configuration + +# CONFIG_USE_GPIO is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +# CONFIG_ENABLE_FXMAC is not set +CONFIG_ENABLE_FGMAC=y +CONFIG_FGMAC_PHY_COMMON=y +# CONFIG_FGMAC_PHY_AR803X is not set +# end of Eth Configuration + +# CONFIG_USE_CAN is not set +# CONFIG_USE_I2C is not set +# CONFIG_USE_TIMER is not set +# CONFIG_USE_MIO is not set +# CONFIG_USE_SDMMC is not set +# CONFIG_USE_PCIE is not set +# CONFIG_USE_WDT is not set +# CONFIG_USE_DMA is not set +# CONFIG_USE_NAND is not set +# CONFIG_USE_RTC is not set +# CONFIG_USE_SATA is not set +# CONFIG_USE_ADC is not set +# CONFIG_USE_PWM is not set +# CONFIG_USE_IPC is not set +# CONFIG_USE_MEDIA is not set +# CONFIG_USE_SCMI_MHU is not set +# CONFIG_USE_I2S is not set +# CONFIG_USE_I3C is not set +# end of Drivers configuration + +# +# Build setup +# +CONFIG_CHECK_DEPS=y +CONFIG_OUTPUT_BINARY=y + +# +# Optimization options +# +# CONFIG_DEBUG_NOOPT is not set +# CONFIG_DEBUG_CUSTOMOPT is not set +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y +CONFIG_DEBUG_LINK_MAP=y +# CONFIG_CCACHE is not set +# CONFIG_ARCH_COVERAGE is not set +# CONFIG_LTO_FULL is not set +# end of Optimization options + +# +# Debug options +# +# CONFIG_DEBUG_ENABLE_ALL_WARNING is not set +# CONFIG_WALL_WARNING_ERROR is not set +# CONFIG_STRICT_PROTOTYPES is not set +# CONFIG_DEBUG_SYMBOLS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_OUTPUT_ASM_DIS is not set +# CONFIG_ENABLE_WSHADOW is not set +# CONFIG_ENABLE_WUNDEF is not set +CONFIG_DOWNGRADE_DIAG_WARNING=y +# end of Debug options + +# +# Lib +# +CONFIG_USE_COMPILE_CHAIN=y +# CONFIG_USE_NEWLIB is not set +# CONFIG_USE_USER_DEFINED is not set +# end of Lib + +# CONFIG_ENABLE_CXX is not set + +# +# Linker Options +# +CONFIG_DEFAULT_LINKER_SCRIPT=y +# CONFIG_USER_DEFINED_LD is not set +CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 +CONFIG_HEAP_SIZE=1 +CONFIG_STACK_SIZE=0x400 +# end of Linker Options +# end of Build setup + +# +# Component Configuration +# + +# +# Freertos Uart Drivers +# +CONFIG_FREERTOS_USE_UART=y +# end of Freertos Uart Drivers + +# +# Freertos Pwm Drivers +# +# CONFIG_FREERTOS_USE_PWM is not set +# end of Freertos Pwm Drivers + +# +# Freertos Qspi Drivers +# +# CONFIG_FREERTOS_USE_QSPI is not set +# end of Freertos Qspi Drivers + +# +# Freertos Wdt Drivers +# +# CONFIG_FREERTOS_USE_WDT is not set +# end of Freertos Wdt Drivers + +# +# Freertos Eth Drivers +# +# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_GMAC=y +# end of Freertos Eth Drivers + +# +# Freertos Spim Drivers +# +# CONFIG_FREERTOS_USE_FSPIM is not set +# end of Freertos Spim Drivers + +# +# Freertos DMA Drivers +# +# CONFIG_FREERTOS_USE_FDDMA is not set +# CONFIG_FREERTOS_USE_FGDMA is not set +# end of Freertos DMA Drivers + +# +# Freertos Adc Drivers +# +# CONFIG_FREERTOS_USE_ADC is not set +# end of Freertos Adc Drivers + +# +# Freertos Can Drivers +# +# CONFIG_FREERTOS_USE_CAN is not set +# end of Freertos Can Drivers + +# +# Freertos I2c Drivers +# +# CONFIG_FREERTOS_USE_I2C is not set +# end of Freertos I2c Drivers + +# +# Freertos Mio Drivers +# +# CONFIG_FREERTOS_USE_MIO is not set +# end of Freertos Mio Drivers + +# +# Freertos Timer Drivers +# +# CONFIG_FREERTOS_USE_TIMER is not set +# end of Freertos Timer Drivers + +# +# Freertos Media Drivers +# +# CONFIG_FREERTOS_USE_MEDIA is not set +# end of Freertos Media Drivers + +# +# Freertos I2s Drivers +# +# CONFIG_FREERTOS_USE_I2S is not set +# end of Freertos I2s Drivers +# end of Component Configuration + +# +# Third-party configuration +# +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +# CONFIG_LWIP_FXMAC is not set +CONFIG_LWIP_FGMAC=y +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + +# CONFIG_USE_AMP is not set +# CONFIG_USE_YMODEM is not set +# CONFIG_USE_SFUD is not set +CONFIG_USE_BACKTRACE=y +# CONFIG_USE_FATFS_0_1_4 is not set +CONFIG_USE_TLSF=y +# CONFIG_USE_SPIFFS is not set +# CONFIG_USE_LITTLE_FS is not set +# CONFIG_USE_LVGL is not set +# CONFIG_USE_FREEMODBUS is not set +# CONFIG_USE_CHERRY_USB is not set +# CONFIG_USE_FSL_SDMMC is not set +# CONFIG_USE_FSL_WIFI is not set +# end of Third-party configuration + +# +# FreeRTOS Kernel Configuration +# +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set +CONFIG_FREERTOS_MAX_PRIORITIES=32 +CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 +CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_MINIMAL_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=32 +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set +CONFIG_FREERTOS_TOTAL_HEAP_SIZE=10240 +CONFIG_FREERTOS_TASK_FPU_SUPPORT=1 +# CONFIG_FREERTOS_USE_POSIX is not set +# end of FreeRTOS Kernel Configuration diff --git a/example/peripheral/media/media_test/configs/e2000d_aarch32_demo_freertos.config b/example/network/lwip_https/configs/e2000d_aarch32_demo_lwip_https.config similarity index 58% rename from example/peripheral/media/media_test/configs/e2000d_aarch32_demo_freertos.config rename to example/network/lwip_https/configs/e2000d_aarch32_demo_lwip_https.config index fa32385e..6ae23dfc 100644 --- a/example/peripheral/media/media_test/configs/e2000d_aarch32_demo_freertos.config +++ b/example/network/lwip_https/configs/e2000d_aarch32_demo_lwip_https.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -92,7 +93,7 @@ CONFIG_BOARD_NAME="demo" # # Build project name # -CONFIG_TARGET_NAME="freertos" +CONFIG_TARGET_NAME="lwip_https" # end of Build project name # end of Board Configuration @@ -101,10 +102,10 @@ CONFIG_TARGET_NAME="freertos" # CONFIG_ELOG_LINE_BUF_SIZE=0x100 # CONFIG_LOG_VERBOS is not set -CONFIG_LOG_DEBUG=y +# CONFIG_LOG_DEBUG is not set # CONFIG_LOG_INFO is not set # CONFIG_LOG_WARN is not set -# CONFIG_LOG_ERROR is not set +CONFIG_LOG_ERROR=y # CONFIG_LOG_NONE is not set # CONFIG_LOG_EXTRA_INFO is not set # CONFIG_LOG_DISPALY_CORE_NUM is not set @@ -112,6 +113,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -131,7 +133,17 @@ CONFIG_ENABLE_Pl011_UART=y # end of Usart Configuration # CONFIG_USE_GPIO is not set -# CONFIG_USE_ETH is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + # CONFIG_USE_CAN is not set # CONFIG_USE_I2C is not set # CONFIG_USE_TIMER is not set @@ -146,14 +158,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_ADC is not set # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set -CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +# CONFIG_USE_MEDIA is not set # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -208,7 +213,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x20000000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 CONFIG_HEAP_SIZE=1 CONFIG_SVC_STACK_SIZE=0x1000 CONFIG_SYS_STACK_SIZE=0x1000 @@ -250,7 +255,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Eth Drivers # -# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_XMAC=y # CONFIG_FREERTOS_USE_GMAC is not set # end of Freertos Eth Drivers @@ -300,7 +305,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Media Drivers # -CONFIG_FREERTOS_USE_MEDIA=y +# CONFIG_FREERTOS_USE_MEDIA is not set # end of Freertos Media Drivers # @@ -313,7 +318,252 @@ CONFIG_FREERTOS_USE_MEDIA=y # # Third-party configuration # -# CONFIG_USE_LWIP is not set +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +573,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -330,7 +582,7 @@ CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_USE_SFUD is not set CONFIG_USE_BACKTRACE=y # CONFIG_USE_FATFS_0_1_4 is not set -# CONFIG_USE_TLSF is not set +CONFIG_USE_TLSF=y # CONFIG_USE_SPIFFS is not set # CONFIG_USE_LITTLE_FS is not set # CONFIG_USE_LVGL is not set @@ -345,6 +597,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/e2000d_aarch64_demo_freertos.config b/example/network/lwip_https/configs/e2000d_aarch64_demo_lwip_https.config similarity index 57% rename from example/peripheral/media/media_test/configs/e2000d_aarch64_demo_freertos.config rename to example/network/lwip_https/configs/e2000d_aarch64_demo_lwip_https.config index 2a178386..31aa6e73 100644 --- a/example/peripheral/media/media_test/configs/e2000d_aarch64_demo_freertos.config +++ b/example/network/lwip_https/configs/e2000d_aarch64_demo_lwip_https.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -86,7 +87,7 @@ CONFIG_BOARD_NAME="demo" # # Build project name # -CONFIG_TARGET_NAME="freertos" +CONFIG_TARGET_NAME="lwip_https" # end of Build project name # end of Board Configuration @@ -95,10 +96,10 @@ CONFIG_TARGET_NAME="freertos" # CONFIG_ELOG_LINE_BUF_SIZE=0x100 # CONFIG_LOG_VERBOS is not set -CONFIG_LOG_DEBUG=y +# CONFIG_LOG_DEBUG is not set # CONFIG_LOG_INFO is not set # CONFIG_LOG_WARN is not set -# CONFIG_LOG_ERROR is not set +CONFIG_LOG_ERROR=y # CONFIG_LOG_NONE is not set # CONFIG_LOG_EXTRA_INFO is not set # CONFIG_LOG_DISPALY_CORE_NUM is not set @@ -106,6 +107,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -125,7 +127,17 @@ CONFIG_ENABLE_Pl011_UART=y # end of Usart Configuration # CONFIG_USE_GPIO is not set -# CONFIG_USE_ETH is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + # CONFIG_USE_CAN is not set # CONFIG_USE_I2C is not set # CONFIG_USE_TIMER is not set @@ -140,14 +152,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_ADC is not set # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set -CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +# CONFIG_USE_MEDIA is not set # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -202,7 +207,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x20000000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 CONFIG_HEAP_SIZE=1 CONFIG_STACK_SIZE=0x400 # end of Linker Options @@ -239,7 +244,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Eth Drivers # -# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_XMAC=y # CONFIG_FREERTOS_USE_GMAC is not set # end of Freertos Eth Drivers @@ -289,7 +294,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Media Drivers # -CONFIG_FREERTOS_USE_MEDIA=y +# CONFIG_FREERTOS_USE_MEDIA is not set # end of Freertos Media Drivers # @@ -302,7 +307,252 @@ CONFIG_FREERTOS_USE_MEDIA=y # # Third-party configuration # -# CONFIG_USE_LWIP is not set +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +562,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -319,7 +571,7 @@ CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_USE_SFUD is not set CONFIG_USE_BACKTRACE=y # CONFIG_USE_FATFS_0_1_4 is not set -# CONFIG_USE_TLSF is not set +CONFIG_USE_TLSF=y # CONFIG_USE_SPIFFS is not set # CONFIG_USE_LITTLE_FS is not set # CONFIG_USE_LVGL is not set @@ -334,6 +586,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/e2000q_aarch32_demo_freertos.config b/example/network/lwip_https/configs/e2000q_aarch32_demo_lwip_https.config similarity index 58% rename from example/peripheral/media/media_test/configs/e2000q_aarch32_demo_freertos.config rename to example/network/lwip_https/configs/e2000q_aarch32_demo_lwip_https.config index 5ed7b7db..21dee350 100644 --- a/example/peripheral/media/media_test/configs/e2000q_aarch32_demo_freertos.config +++ b/example/network/lwip_https/configs/e2000q_aarch32_demo_lwip_https.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -91,7 +92,7 @@ CONFIG_E2000Q_DEMO_BOARD=y # # Build project name # -CONFIG_TARGET_NAME="freertos" +CONFIG_TARGET_NAME="lwip_https" # end of Build project name # end of Board Configuration @@ -100,10 +101,10 @@ CONFIG_TARGET_NAME="freertos" # CONFIG_ELOG_LINE_BUF_SIZE=0x100 # CONFIG_LOG_VERBOS is not set -CONFIG_LOG_DEBUG=y +# CONFIG_LOG_DEBUG is not set # CONFIG_LOG_INFO is not set # CONFIG_LOG_WARN is not set -# CONFIG_LOG_ERROR is not set +CONFIG_LOG_ERROR=y # CONFIG_LOG_NONE is not set # CONFIG_LOG_EXTRA_INFO is not set # CONFIG_LOG_DISPALY_CORE_NUM is not set @@ -111,6 +112,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -130,7 +132,17 @@ CONFIG_ENABLE_Pl011_UART=y # end of Usart Configuration # CONFIG_USE_GPIO is not set -# CONFIG_USE_ETH is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + # CONFIG_USE_CAN is not set # CONFIG_USE_I2C is not set # CONFIG_USE_TIMER is not set @@ -145,14 +157,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_ADC is not set # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set -CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +# CONFIG_USE_MEDIA is not set # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -207,7 +212,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x20000000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 CONFIG_HEAP_SIZE=1 CONFIG_SVC_STACK_SIZE=0x1000 CONFIG_SYS_STACK_SIZE=0x1000 @@ -249,7 +254,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Eth Drivers # -# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_XMAC=y # CONFIG_FREERTOS_USE_GMAC is not set # end of Freertos Eth Drivers @@ -299,7 +304,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Media Drivers # -CONFIG_FREERTOS_USE_MEDIA=y +# CONFIG_FREERTOS_USE_MEDIA is not set # end of Freertos Media Drivers # @@ -312,7 +317,252 @@ CONFIG_FREERTOS_USE_MEDIA=y # # Third-party configuration # -# CONFIG_USE_LWIP is not set +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +572,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -329,7 +581,7 @@ CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_USE_SFUD is not set CONFIG_USE_BACKTRACE=y # CONFIG_USE_FATFS_0_1_4 is not set -# CONFIG_USE_TLSF is not set +CONFIG_USE_TLSF=y # CONFIG_USE_SPIFFS is not set # CONFIG_USE_LITTLE_FS is not set # CONFIG_USE_LVGL is not set @@ -344,6 +596,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/e2000q_aarch64_demo_freertos.config b/example/network/lwip_https/configs/e2000q_aarch64_demo_lwip_https.config similarity index 57% rename from example/peripheral/media/media_test/configs/e2000q_aarch64_demo_freertos.config rename to example/network/lwip_https/configs/e2000q_aarch64_demo_lwip_https.config index 225ecf5d..48bed033 100644 --- a/example/peripheral/media/media_test/configs/e2000q_aarch64_demo_freertos.config +++ b/example/network/lwip_https/configs/e2000q_aarch64_demo_lwip_https.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -85,7 +86,7 @@ CONFIG_E2000Q_DEMO_BOARD=y # # Build project name # -CONFIG_TARGET_NAME="freertos" +CONFIG_TARGET_NAME="lwip_https" # end of Build project name # end of Board Configuration @@ -94,10 +95,10 @@ CONFIG_TARGET_NAME="freertos" # CONFIG_ELOG_LINE_BUF_SIZE=0x100 # CONFIG_LOG_VERBOS is not set -CONFIG_LOG_DEBUG=y +# CONFIG_LOG_DEBUG is not set # CONFIG_LOG_INFO is not set # CONFIG_LOG_WARN is not set -# CONFIG_LOG_ERROR is not set +CONFIG_LOG_ERROR=y # CONFIG_LOG_NONE is not set # CONFIG_LOG_EXTRA_INFO is not set # CONFIG_LOG_DISPALY_CORE_NUM is not set @@ -105,6 +106,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -124,7 +126,17 @@ CONFIG_ENABLE_Pl011_UART=y # end of Usart Configuration # CONFIG_USE_GPIO is not set -# CONFIG_USE_ETH is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + # CONFIG_USE_CAN is not set # CONFIG_USE_I2C is not set # CONFIG_USE_TIMER is not set @@ -139,14 +151,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_ADC is not set # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set -CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +# CONFIG_USE_MEDIA is not set # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -201,7 +206,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x20000000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 CONFIG_HEAP_SIZE=1 CONFIG_STACK_SIZE=0x400 # end of Linker Options @@ -238,7 +243,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Eth Drivers # -# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_XMAC=y # CONFIG_FREERTOS_USE_GMAC is not set # end of Freertos Eth Drivers @@ -288,7 +293,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Media Drivers # -CONFIG_FREERTOS_USE_MEDIA=y +# CONFIG_FREERTOS_USE_MEDIA is not set # end of Freertos Media Drivers # @@ -301,7 +306,252 @@ CONFIG_FREERTOS_USE_MEDIA=y # # Third-party configuration # -# CONFIG_USE_LWIP is not set +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +561,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -318,7 +570,7 @@ CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_USE_SFUD is not set CONFIG_USE_BACKTRACE=y # CONFIG_USE_FATFS_0_1_4 is not set -# CONFIG_USE_TLSF is not set +CONFIG_USE_TLSF=y # CONFIG_USE_SPIFFS is not set # CONFIG_USE_LITTLE_FS is not set # CONFIG_USE_LVGL is not set @@ -333,6 +585,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_https/configs/ft2004_aarch32_dsk_lwip_https.config b/example/network/lwip_https/configs/ft2004_aarch32_dsk_lwip_https.config new file mode 100644 index 00000000..65d6ba04 --- /dev/null +++ b/example/network/lwip_https/configs/ft2004_aarch32_dsk_lwip_https.config @@ -0,0 +1,606 @@ +CONFIG_USE_FREERTOS=y + +# +# Arch configuration +# +CONFIG_TARGET_ARMv8=y +CONFIG_ARCH_NAME="armv8" + +# +# Arm architecture configuration +# +# CONFIG_ARCH_ARMV8_AARCH64 is not set +CONFIG_ARCH_ARMV8_AARCH32=y + +# +# Compiler configuration +# +CONFIG_ARM_GCC_SELECT=y +# CONFIG_ARM_CLANG_SELECT is not set +CONFIG_TOOLCHAIN_NAME="gcc" +CONFIG_TARGET_ARMV8_AARCH32=y +CONFIG_ARCH_EXECUTION_STATE="aarch32" + +# +# Fpu configuration +# +CONFIG_CRYPTO_NEON_FP_ARMV8=y +# CONFIG_VFPV4 is not set +# CONFIG_VFPV4_D16 is not set +# CONFIG_VFPV3 is not set +# CONFIG_VFPV3_D16 is not set +CONFIG_ARM_MFPU="crypto-neon-fp-armv8" +CONFIG_MFLOAT_ABI_HARD=y +# CONFIG_MFLOAT_ABI_SOFTFP is not set +CONFIG_ARM_MFLOAT_ABI="hard" +# end of Fpu configuration +# end of Compiler configuration + +# CONFIG_USE_L3CACHE is not set +CONFIG_USE_AARCH64_L1_TO_AARCH32=y +# end of Arm architecture configuration + +CONFIG_MMU_PAGE_SIZE=0x1000 +CONFIG_FMMU_NUM_L2_TABLES=256 +# end of Arch configuration + +# +# Soc configuration +# +# CONFIG_TARGET_PHYTIUMPI is not set +# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_E2000D is not set +# CONFIG_TARGET_E2000S is not set +CONFIG_TARGET_FT2004=y +# CONFIG_TARGET_D2000 is not set +# CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="ft2004" +CONFIG_SOC_CORE_NUM=4 +CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 +CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 +CONFIG_F64BIT_MEMORY_ADDRESS=0x2000000000 +CONFIG_F64BIT_MEMORY_LENGTH=0x800000000 +CONFIG_DEFAULT_DEBUG_PRINT_UART1=y +# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set +# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set +# end of Soc configuration + +# +# Board Configuration +# +CONFIG_BOARD_NAME="dsk" +CONFIG_FT2004_DSK_BOARD=y + +# +# IO mux configuration when board start up +# +# CONFIG_CUS_DEMO_BOARD is not set + +# +# Build project name +# +CONFIG_TARGET_NAME="lwip_https" +# end of Build project name +# end of Board Configuration + +# +# Sdk common configuration +# +CONFIG_ELOG_LINE_BUF_SIZE=0x100 +# CONFIG_LOG_VERBOS is not set +# CONFIG_LOG_DEBUG is not set +# CONFIG_LOG_INFO is not set +# CONFIG_LOG_WARN is not set +CONFIG_LOG_ERROR=y +# CONFIG_LOG_NONE is not set +# CONFIG_LOG_EXTRA_INFO is not set +# CONFIG_LOG_DISPALY_CORE_NUM is not set +# CONFIG_BOOTUP_DEBUG_PRINTS is not set +CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y +CONFIG_INTERRUPT_ROLE_MASTER=y +# CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set +# end of Sdk common configuration + +# +# Drivers configuration +# +CONFIG_USE_IOMUX=y +CONFIG_ENABLE_IOCTRL=y +# CONFIG_ENABLE_IOPAD is not set +# CONFIG_USE_SPI is not set +# CONFIG_USE_QSPI is not set +CONFIG_USE_SERIAL=y + +# +# Usart Configuration +# +CONFIG_ENABLE_Pl011_UART=y +# end of Usart Configuration + +# CONFIG_USE_GPIO is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +# CONFIG_ENABLE_FXMAC is not set +CONFIG_ENABLE_FGMAC=y +CONFIG_FGMAC_PHY_COMMON=y +# CONFIG_FGMAC_PHY_AR803X is not set +# end of Eth Configuration + +# CONFIG_USE_CAN is not set +# CONFIG_USE_I2C is not set +# CONFIG_USE_TIMER is not set +# CONFIG_USE_MIO is not set +# CONFIG_USE_SDMMC is not set +# CONFIG_USE_PCIE is not set +# CONFIG_USE_WDT is not set +# CONFIG_USE_DMA is not set +# CONFIG_USE_NAND is not set +# CONFIG_USE_RTC is not set +# CONFIG_USE_SATA is not set +# CONFIG_USE_ADC is not set +# CONFIG_USE_PWM is not set +# CONFIG_USE_IPC is not set +# CONFIG_USE_MEDIA is not set +# CONFIG_USE_SCMI_MHU is not set +# CONFIG_USE_I2S is not set +# CONFIG_USE_I3C is not set +# end of Drivers configuration + +# +# Build setup +# +CONFIG_CHECK_DEPS=y +CONFIG_OUTPUT_BINARY=y + +# +# Optimization options +# +# CONFIG_DEBUG_NOOPT is not set +# CONFIG_DEBUG_CUSTOMOPT is not set +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y +CONFIG_DEBUG_LINK_MAP=y +# CONFIG_CCACHE is not set +# CONFIG_ARCH_COVERAGE is not set +# CONFIG_LTO_FULL is not set +# end of Optimization options + +# +# Debug options +# +# CONFIG_DEBUG_ENABLE_ALL_WARNING is not set +# CONFIG_WALL_WARNING_ERROR is not set +# CONFIG_STRICT_PROTOTYPES is not set +# CONFIG_DEBUG_SYMBOLS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_OUTPUT_ASM_DIS is not set +# CONFIG_ENABLE_WSHADOW is not set +# CONFIG_ENABLE_WUNDEF is not set +CONFIG_DOWNGRADE_DIAG_WARNING=y +# end of Debug options + +# +# Lib +# +CONFIG_USE_COMPILE_CHAIN=y +# CONFIG_USE_NEWLIB is not set +# CONFIG_USE_USER_DEFINED is not set +# end of Lib + +# CONFIG_ENABLE_CXX is not set + +# +# Linker Options +# +CONFIG_DEFAULT_LINKER_SCRIPT=y +# CONFIG_USER_DEFINED_LD is not set +CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 +CONFIG_HEAP_SIZE=1 +CONFIG_SVC_STACK_SIZE=0x1000 +CONFIG_SYS_STACK_SIZE=0x1000 +CONFIG_IRQ_STACK_SIZE=0x1000 +CONFIG_ABORT_STACK_SIZE=0x1000 +CONFIG_FIQ_STACK_SIZE=0x1000 +CONFIG_UNDEF_STACK_SIZE=0x1000 +# end of Linker Options +# end of Build setup + +# +# Component Configuration +# + +# +# Freertos Uart Drivers +# +CONFIG_FREERTOS_USE_UART=y +# end of Freertos Uart Drivers + +# +# Freertos Pwm Drivers +# +# CONFIG_FREERTOS_USE_PWM is not set +# end of Freertos Pwm Drivers + +# +# Freertos Qspi Drivers +# +# CONFIG_FREERTOS_USE_QSPI is not set +# end of Freertos Qspi Drivers + +# +# Freertos Wdt Drivers +# +# CONFIG_FREERTOS_USE_WDT is not set +# end of Freertos Wdt Drivers + +# +# Freertos Eth Drivers +# +# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_GMAC=y +# end of Freertos Eth Drivers + +# +# Freertos Spim Drivers +# +# CONFIG_FREERTOS_USE_FSPIM is not set +# end of Freertos Spim Drivers + +# +# Freertos DMA Drivers +# +# CONFIG_FREERTOS_USE_FDDMA is not set +# CONFIG_FREERTOS_USE_FGDMA is not set +# end of Freertos DMA Drivers + +# +# Freertos Adc Drivers +# +# CONFIG_FREERTOS_USE_ADC is not set +# end of Freertos Adc Drivers + +# +# Freertos Can Drivers +# +# CONFIG_FREERTOS_USE_CAN is not set +# end of Freertos Can Drivers + +# +# Freertos I2c Drivers +# +# CONFIG_FREERTOS_USE_I2C is not set +# end of Freertos I2c Drivers + +# +# Freertos Mio Drivers +# +# CONFIG_FREERTOS_USE_MIO is not set +# end of Freertos Mio Drivers + +# +# Freertos Timer Drivers +# +# CONFIG_FREERTOS_USE_TIMER is not set +# end of Freertos Timer Drivers + +# +# Freertos Media Drivers +# +# CONFIG_FREERTOS_USE_MEDIA is not set +# end of Freertos Media Drivers + +# +# Freertos I2s Drivers +# +# CONFIG_FREERTOS_USE_I2S is not set +# end of Freertos I2s Drivers +# end of Component Configuration + +# +# Third-party configuration +# +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +# CONFIG_LWIP_FXMAC is not set +CONFIG_LWIP_FGMAC=y +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + +# CONFIG_USE_AMP is not set +# CONFIG_USE_YMODEM is not set +# CONFIG_USE_SFUD is not set +CONFIG_USE_BACKTRACE=y +# CONFIG_USE_FATFS_0_1_4 is not set +CONFIG_USE_TLSF=y +# CONFIG_USE_SPIFFS is not set +# CONFIG_USE_LITTLE_FS is not set +# CONFIG_USE_LVGL is not set +# CONFIG_USE_FREEMODBUS is not set +# CONFIG_USE_CHERRY_USB is not set +# CONFIG_USE_FSL_SDMMC is not set +# CONFIG_USE_FSL_WIFI is not set +# end of Third-party configuration + +# +# FreeRTOS Kernel Configuration +# +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set +CONFIG_FREERTOS_MAX_PRIORITIES=32 +CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 +CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_MINIMAL_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=32 +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set +CONFIG_FREERTOS_TOTAL_HEAP_SIZE=10240 +CONFIG_FREERTOS_TASK_FPU_SUPPORT=1 +# CONFIG_FREERTOS_USE_POSIX is not set +# end of FreeRTOS Kernel Configuration diff --git a/example/network/lwip_https/configs/ft2004_aarch64_dsk_lwip_https.config b/example/network/lwip_https/configs/ft2004_aarch64_dsk_lwip_https.config new file mode 100644 index 00000000..ff832d48 --- /dev/null +++ b/example/network/lwip_https/configs/ft2004_aarch64_dsk_lwip_https.config @@ -0,0 +1,595 @@ +CONFIG_USE_FREERTOS=y + +# +# Arch configuration +# +CONFIG_TARGET_ARMv8=y +CONFIG_ARCH_NAME="armv8" + +# +# Arm architecture configuration +# +CONFIG_ARCH_ARMV8_AARCH64=y +# CONFIG_ARCH_ARMV8_AARCH32 is not set + +# +# Compiler configuration +# +CONFIG_ARM_GCC_SELECT=y +# CONFIG_ARM_CLANG_SELECT is not set +CONFIG_TOOLCHAIN_NAME="gcc" +CONFIG_TARGET_ARMV8_AARCH64=y +CONFIG_ARCH_EXECUTION_STATE="aarch64" +CONFIG_ARM_NEON=y +CONFIG_ARM_CRC=y +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_FLOAT_POINT=y +# CONFIG_GCC_CODE_MODEL_TINY is not set +CONFIG_GCC_CODE_MODEL_SMALL=y +# CONFIG_GCC_CODE_MODEL_LARGE is not set +# end of Compiler configuration + +# CONFIG_USE_L3CACHE is not set +# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +# CONFIG_MMU_DEBUG_PRINTS is not set +# end of Arm architecture configuration + +CONFIG_MMU_PAGE_SIZE=0x1000 +CONFIG_MAX_XLAT_TABLES=256 +# end of Arch configuration + +# +# Soc configuration +# +# CONFIG_TARGET_PHYTIUMPI is not set +# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_E2000D is not set +# CONFIG_TARGET_E2000S is not set +CONFIG_TARGET_FT2004=y +# CONFIG_TARGET_D2000 is not set +# CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="ft2004" +CONFIG_SOC_CORE_NUM=4 +CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 +CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 +CONFIG_F64BIT_MEMORY_ADDRESS=0x2000000000 +CONFIG_F64BIT_MEMORY_LENGTH=0x800000000 +CONFIG_DEFAULT_DEBUG_PRINT_UART1=y +# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set +# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set +# end of Soc configuration + +# +# Board Configuration +# +CONFIG_BOARD_NAME="dsk" +CONFIG_FT2004_DSK_BOARD=y + +# +# IO mux configuration when board start up +# +# CONFIG_CUS_DEMO_BOARD is not set + +# +# Build project name +# +CONFIG_TARGET_NAME="lwip_https" +# end of Build project name +# end of Board Configuration + +# +# Sdk common configuration +# +CONFIG_ELOG_LINE_BUF_SIZE=0x100 +# CONFIG_LOG_VERBOS is not set +# CONFIG_LOG_DEBUG is not set +# CONFIG_LOG_INFO is not set +# CONFIG_LOG_WARN is not set +CONFIG_LOG_ERROR=y +# CONFIG_LOG_NONE is not set +# CONFIG_LOG_EXTRA_INFO is not set +# CONFIG_LOG_DISPALY_CORE_NUM is not set +# CONFIG_BOOTUP_DEBUG_PRINTS is not set +CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y +CONFIG_INTERRUPT_ROLE_MASTER=y +# CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set +# end of Sdk common configuration + +# +# Drivers configuration +# +CONFIG_USE_IOMUX=y +CONFIG_ENABLE_IOCTRL=y +# CONFIG_ENABLE_IOPAD is not set +# CONFIG_USE_SPI is not set +# CONFIG_USE_QSPI is not set +CONFIG_USE_SERIAL=y + +# +# Usart Configuration +# +CONFIG_ENABLE_Pl011_UART=y +# end of Usart Configuration + +# CONFIG_USE_GPIO is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +# CONFIG_ENABLE_FXMAC is not set +CONFIG_ENABLE_FGMAC=y +CONFIG_FGMAC_PHY_COMMON=y +# CONFIG_FGMAC_PHY_AR803X is not set +# end of Eth Configuration + +# CONFIG_USE_CAN is not set +# CONFIG_USE_I2C is not set +# CONFIG_USE_TIMER is not set +# CONFIG_USE_MIO is not set +# CONFIG_USE_SDMMC is not set +# CONFIG_USE_PCIE is not set +# CONFIG_USE_WDT is not set +# CONFIG_USE_DMA is not set +# CONFIG_USE_NAND is not set +# CONFIG_USE_RTC is not set +# CONFIG_USE_SATA is not set +# CONFIG_USE_ADC is not set +# CONFIG_USE_PWM is not set +# CONFIG_USE_IPC is not set +# CONFIG_USE_MEDIA is not set +# CONFIG_USE_SCMI_MHU is not set +# CONFIG_USE_I2S is not set +# CONFIG_USE_I3C is not set +# end of Drivers configuration + +# +# Build setup +# +CONFIG_CHECK_DEPS=y +CONFIG_OUTPUT_BINARY=y + +# +# Optimization options +# +# CONFIG_DEBUG_NOOPT is not set +# CONFIG_DEBUG_CUSTOMOPT is not set +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y +CONFIG_DEBUG_LINK_MAP=y +# CONFIG_CCACHE is not set +# CONFIG_ARCH_COVERAGE is not set +# CONFIG_LTO_FULL is not set +# end of Optimization options + +# +# Debug options +# +# CONFIG_DEBUG_ENABLE_ALL_WARNING is not set +# CONFIG_WALL_WARNING_ERROR is not set +# CONFIG_STRICT_PROTOTYPES is not set +# CONFIG_DEBUG_SYMBOLS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_OUTPUT_ASM_DIS is not set +# CONFIG_ENABLE_WSHADOW is not set +# CONFIG_ENABLE_WUNDEF is not set +CONFIG_DOWNGRADE_DIAG_WARNING=y +# end of Debug options + +# +# Lib +# +CONFIG_USE_COMPILE_CHAIN=y +# CONFIG_USE_NEWLIB is not set +# CONFIG_USE_USER_DEFINED is not set +# end of Lib + +# CONFIG_ENABLE_CXX is not set + +# +# Linker Options +# +CONFIG_DEFAULT_LINKER_SCRIPT=y +# CONFIG_USER_DEFINED_LD is not set +CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 +CONFIG_HEAP_SIZE=1 +CONFIG_STACK_SIZE=0x400 +# end of Linker Options +# end of Build setup + +# +# Component Configuration +# + +# +# Freertos Uart Drivers +# +CONFIG_FREERTOS_USE_UART=y +# end of Freertos Uart Drivers + +# +# Freertos Pwm Drivers +# +# CONFIG_FREERTOS_USE_PWM is not set +# end of Freertos Pwm Drivers + +# +# Freertos Qspi Drivers +# +# CONFIG_FREERTOS_USE_QSPI is not set +# end of Freertos Qspi Drivers + +# +# Freertos Wdt Drivers +# +# CONFIG_FREERTOS_USE_WDT is not set +# end of Freertos Wdt Drivers + +# +# Freertos Eth Drivers +# +# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_GMAC=y +# end of Freertos Eth Drivers + +# +# Freertos Spim Drivers +# +# CONFIG_FREERTOS_USE_FSPIM is not set +# end of Freertos Spim Drivers + +# +# Freertos DMA Drivers +# +# CONFIG_FREERTOS_USE_FDDMA is not set +# CONFIG_FREERTOS_USE_FGDMA is not set +# end of Freertos DMA Drivers + +# +# Freertos Adc Drivers +# +# CONFIG_FREERTOS_USE_ADC is not set +# end of Freertos Adc Drivers + +# +# Freertos Can Drivers +# +# CONFIG_FREERTOS_USE_CAN is not set +# end of Freertos Can Drivers + +# +# Freertos I2c Drivers +# +# CONFIG_FREERTOS_USE_I2C is not set +# end of Freertos I2c Drivers + +# +# Freertos Mio Drivers +# +# CONFIG_FREERTOS_USE_MIO is not set +# end of Freertos Mio Drivers + +# +# Freertos Timer Drivers +# +# CONFIG_FREERTOS_USE_TIMER is not set +# end of Freertos Timer Drivers + +# +# Freertos Media Drivers +# +# CONFIG_FREERTOS_USE_MEDIA is not set +# end of Freertos Media Drivers + +# +# Freertos I2s Drivers +# +# CONFIG_FREERTOS_USE_I2S is not set +# end of Freertos I2s Drivers +# end of Component Configuration + +# +# Third-party configuration +# +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +# CONFIG_LWIP_FXMAC is not set +CONFIG_LWIP_FGMAC=y +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + +# CONFIG_USE_AMP is not set +# CONFIG_USE_YMODEM is not set +# CONFIG_USE_SFUD is not set +CONFIG_USE_BACKTRACE=y +# CONFIG_USE_FATFS_0_1_4 is not set +CONFIG_USE_TLSF=y +# CONFIG_USE_SPIFFS is not set +# CONFIG_USE_LITTLE_FS is not set +# CONFIG_USE_LVGL is not set +# CONFIG_USE_FREEMODBUS is not set +# CONFIG_USE_CHERRY_USB is not set +# CONFIG_USE_FSL_SDMMC is not set +# CONFIG_USE_FSL_WIFI is not set +# end of Third-party configuration + +# +# FreeRTOS Kernel Configuration +# +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set +CONFIG_FREERTOS_MAX_PRIORITIES=32 +CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 +CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_MINIMAL_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=32 +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set +CONFIG_FREERTOS_TOTAL_HEAP_SIZE=10240 +CONFIG_FREERTOS_TASK_FPU_SUPPORT=1 +# CONFIG_FREERTOS_USE_POSIX is not set +# end of FreeRTOS Kernel Configuration diff --git a/example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_freertos.config b/example/network/lwip_https/configs/phytiumpi_aarch32_firefly_lwip_https.config similarity index 58% rename from example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_freertos.config rename to example/network/lwip_https/configs/phytiumpi_aarch32_firefly_lwip_https.config index 4cf49b27..878de18d 100644 --- a/example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_freertos.config +++ b/example/network/lwip_https/configs/phytiumpi_aarch32_firefly_lwip_https.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -90,7 +91,7 @@ CONFIG_FIREFLY_DEMO_BOARD=y # # Build project name # -CONFIG_TARGET_NAME="freertos" +CONFIG_TARGET_NAME="lwip_https" # end of Build project name # end of Board Configuration @@ -99,10 +100,10 @@ CONFIG_TARGET_NAME="freertos" # CONFIG_ELOG_LINE_BUF_SIZE=0x100 # CONFIG_LOG_VERBOS is not set -CONFIG_LOG_DEBUG=y +# CONFIG_LOG_DEBUG is not set # CONFIG_LOG_INFO is not set # CONFIG_LOG_WARN is not set -# CONFIG_LOG_ERROR is not set +CONFIG_LOG_ERROR=y # CONFIG_LOG_NONE is not set # CONFIG_LOG_EXTRA_INFO is not set # CONFIG_LOG_DISPALY_CORE_NUM is not set @@ -110,6 +111,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -129,7 +131,17 @@ CONFIG_ENABLE_Pl011_UART=y # end of Usart Configuration # CONFIG_USE_GPIO is not set -# CONFIG_USE_ETH is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + # CONFIG_USE_CAN is not set # CONFIG_USE_I2C is not set # CONFIG_USE_TIMER is not set @@ -144,14 +156,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_ADC is not set # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set -CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +# CONFIG_USE_MEDIA is not set # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -206,7 +211,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x20000000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 CONFIG_HEAP_SIZE=1 CONFIG_SVC_STACK_SIZE=0x1000 CONFIG_SYS_STACK_SIZE=0x1000 @@ -248,7 +253,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Eth Drivers # -# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_XMAC=y # CONFIG_FREERTOS_USE_GMAC is not set # end of Freertos Eth Drivers @@ -298,7 +303,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Media Drivers # -CONFIG_FREERTOS_USE_MEDIA=y +# CONFIG_FREERTOS_USE_MEDIA is not set # end of Freertos Media Drivers # @@ -311,7 +316,252 @@ CONFIG_FREERTOS_USE_MEDIA=y # # Third-party configuration # -# CONFIG_USE_LWIP is not set +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +571,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,7 +580,7 @@ CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_USE_SFUD is not set CONFIG_USE_BACKTRACE=y # CONFIG_USE_FATFS_0_1_4 is not set -# CONFIG_USE_TLSF is not set +CONFIG_USE_TLSF=y # CONFIG_USE_SPIFFS is not set # CONFIG_USE_LITTLE_FS is not set # CONFIG_USE_LVGL is not set @@ -343,6 +595,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_freertos.config b/example/network/lwip_https/configs/phytiumpi_aarch64_firefly_lwip_https.config similarity index 57% rename from example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_freertos.config rename to example/network/lwip_https/configs/phytiumpi_aarch64_firefly_lwip_https.config index efbfdcc5..3762ee10 100644 --- a/example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_freertos.config +++ b/example/network/lwip_https/configs/phytiumpi_aarch64_firefly_lwip_https.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -84,7 +85,7 @@ CONFIG_FIREFLY_DEMO_BOARD=y # # Build project name # -CONFIG_TARGET_NAME="freertos" +CONFIG_TARGET_NAME="lwip_https" # end of Build project name # end of Board Configuration @@ -93,10 +94,10 @@ CONFIG_TARGET_NAME="freertos" # CONFIG_ELOG_LINE_BUF_SIZE=0x100 # CONFIG_LOG_VERBOS is not set -CONFIG_LOG_DEBUG=y +# CONFIG_LOG_DEBUG is not set # CONFIG_LOG_INFO is not set # CONFIG_LOG_WARN is not set -# CONFIG_LOG_ERROR is not set +CONFIG_LOG_ERROR=y # CONFIG_LOG_NONE is not set # CONFIG_LOG_EXTRA_INFO is not set # CONFIG_LOG_DISPALY_CORE_NUM is not set @@ -104,6 +105,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -123,7 +125,17 @@ CONFIG_ENABLE_Pl011_UART=y # end of Usart Configuration # CONFIG_USE_GPIO is not set -# CONFIG_USE_ETH is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + # CONFIG_USE_CAN is not set # CONFIG_USE_I2C is not set # CONFIG_USE_TIMER is not set @@ -138,14 +150,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_ADC is not set # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set -CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +# CONFIG_USE_MEDIA is not set # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -200,7 +205,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x20000000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 CONFIG_HEAP_SIZE=1 CONFIG_STACK_SIZE=0x400 # end of Linker Options @@ -237,7 +242,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Eth Drivers # -# CONFIG_FREERTOS_USE_XMAC is not set +CONFIG_FREERTOS_USE_XMAC=y # CONFIG_FREERTOS_USE_GMAC is not set # end of Freertos Eth Drivers @@ -287,7 +292,7 @@ CONFIG_FREERTOS_USE_UART=y # # Freertos Media Drivers # -CONFIG_FREERTOS_USE_MEDIA=y +# CONFIG_FREERTOS_USE_MEDIA is not set # end of Freertos Media Drivers # @@ -300,7 +305,252 @@ CONFIG_FREERTOS_USE_MEDIA=y # # Third-party configuration # -# CONFIG_USE_LWIP is not set +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +560,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -317,7 +569,7 @@ CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_USE_SFUD is not set CONFIG_USE_BACKTRACE=y # CONFIG_USE_FATFS_0_1_4 is not set -# CONFIG_USE_TLSF is not set +CONFIG_USE_TLSF=y # CONFIG_USE_SPIFFS is not set # CONFIG_USE_LITTLE_FS is not set # CONFIG_USE_LVGL is not set @@ -332,6 +584,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_https/fig/https_client.png b/example/network/lwip_https/fig/https_client.png new file mode 100644 index 0000000000000000000000000000000000000000..c77509ed1f33096489a57b94be12a4d7ca885370 GIT binary patch literal 56683 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 SPX$4%YUj^+egDEWDC2K`5K$KZ literal 0 HcmV?d00001 diff --git a/example/network/lwip_https/fig/https_server.png b/example/network/lwip_https/fig/https_server.png new file mode 100644 index 0000000000000000000000000000000000000000..7323e7364fa6356df2980ffcbdb97240c53d1b49 GIT binary patch literal 21774 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 literal 0 HcmV?d00001 diff --git a/example/network/lwip_https/inc/https_example.h b/example/network/lwip_https/inc/https_example.h new file mode 100644 index 00000000..3fec7962 --- /dev/null +++ b/example/network/lwip_https/inc/https_example.h @@ -0,0 +1,51 @@ +/* + * Copyright : (C) 2023 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program 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 Phytium Public License for more details. + * + * + * FilePath: https_example.h + * Created Date: 2024-9-29 16:00:10 + * Last Modified: 2024-09-29 15:52:28 + * Description: This file is for https example function definition. + * + * Modify History: + * Ver Who Date Changes + * ----- ---------- -------- --------------------------------- + * 1.0 huangjin 2024/9/29 first release + */ +#ifndef HTTPS_EXAMPLE_H +#define HTTPS_EXAMPLE_H + +/***************************** Include Files *********************************/ +#include "ftypes.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************** Constant Definitions *****************************/ + +/**************************** Type Definitions *******************************/ + +/************************** Variable Definitions *****************************/ + +/***************** Macros (Inline Functions) Definitions *********************/ + +/************************** Function Prototypes ******************************/ +/* entry function for https example */ +int FFreeRTOSHttpsTaskCreate(void); +void HttpsTestDeinit(void); +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/example/network/lwip_https/main.c b/example/network/lwip_https/main.c new file mode 100644 index 00000000..d0553aa6 --- /dev/null +++ b/example/network/lwip_https/main.c @@ -0,0 +1,77 @@ +/* + * Copyright : (C) 2023 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program 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 Phytium Public License for more details. + * + * + * FilePath: main.c + * Created Date: 2024-09-29 18:26:15 + * Last Modified: 2024-09-29 11:47:17 + * Description: This file is for https example main functions. + * + * Modify History: + * Ver Who Date Changes + * ----- ---------- -------- --------------------------------- + * 1.0 huangjin 2024/9/29 first release + */ + +#include +#include "FreeRTOS.h" +#include "task.h" +#include "lwip/tcpip.h" +#include "sdkconfig.h" +#ifdef CONFIG_USE_LETTER_SHELL +#include "shell_port.h" +#else +#include "https_example.h" + +#define LWIP_HTTPS_EXAMPLE_TASK_PRIORITY 2 + +void HttpsExampleTaskEntry() +{ + /* example functions */ + FFreeRTOSHttpsTaskCreate(); + HttpsTestDeinit(); + + /* end flag */ + printf("[test_end]\r\n"); + vTaskDelete(NULL); +} +#endif + +int main(void) +{ + BaseType_t ret = pdPASS; /* 定义一个创建信息返回值,默认为 pdPASS */ + +#ifdef CONFIG_USE_LETTER_SHELL + ret = LSUserShellTask(); +#else + /* used in no-letter-shell mode */ + ret = xTaskCreate((TaskFunction_t)HttpsExampleTaskEntry, /* 任务入口函数 */ + (const char *)"HttpsExampleTaskEntry", /* 任务名字 */ + 4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)LWIP_HTTPS_EXAMPLE_TASK_PRIORITY, /* 任务优先级 */ + NULL); /* 任务句柄 */ +#endif + if (ret != pdPASS) + { + goto FAIL_EXIT; + } + + tcpip_init(NULL, NULL); + /* 启动任务,开启调度 */ + vTaskStartScheduler(); + while (1); /* 正常不会执行到这里 */ + +FAIL_EXIT: + printf("Failed,the ret value is 0x%x. \r\n", ret); + return -2; +} \ No newline at end of file diff --git a/example/network/lwip_https/makefile b/example/network/lwip_https/makefile new file mode 100644 index 00000000..01747b88 --- /dev/null +++ b/example/network/lwip_https/makefile @@ -0,0 +1,28 @@ +PROJECT_DIR = $(CURDIR) +FREERTOS_SDK_DIR = $(CURDIR)/../../../ + +# # 设置启动镜像名 +BOOT_IMG_NAME ?= freertos + +USER_CSRC := main.c +USER_CSRC += $(wildcard src/*.c) + +USER_INCLUDE := $(PROJECT_DIR) \ + $(PROJECT_DIR)/inc + +include $(FREERTOS_SDK_DIR)/tools/makeall.mk + +# 用户定义的编译目标文件上传路径 +ifeq ($(OS),Windows_NT) +USR_BOOT_DIR ?= /d/tftpboot +else +USR_BOOT_DIR ?= /mnt/d/tftpboot +endif + +image: + $(MAKE) all -j + @cp ./$(IMAGE_OUT_NAME).elf $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).elf +ifdef CONFIG_OUTPUT_BINARY + @cp ./$(IMAGE_OUT_NAME).bin $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).bin +endif + @ls $(USR_BOOT_DIR)/$(BOOT_IMG_NAME).* -l \ No newline at end of file diff --git a/example/network/lwip_https/sdkconfig b/example/network/lwip_https/sdkconfig new file mode 100644 index 00000000..3762ee10 --- /dev/null +++ b/example/network/lwip_https/sdkconfig @@ -0,0 +1,606 @@ +CONFIG_USE_FREERTOS=y + +# +# Arch configuration +# +CONFIG_TARGET_ARMv8=y +CONFIG_ARCH_NAME="armv8" + +# +# Arm architecture configuration +# +CONFIG_ARCH_ARMV8_AARCH64=y +# CONFIG_ARCH_ARMV8_AARCH32 is not set + +# +# Compiler configuration +# +CONFIG_ARM_GCC_SELECT=y +# CONFIG_ARM_CLANG_SELECT is not set +CONFIG_TOOLCHAIN_NAME="gcc" +CONFIG_TARGET_ARMV8_AARCH64=y +CONFIG_ARCH_EXECUTION_STATE="aarch64" +CONFIG_ARM_NEON=y +CONFIG_ARM_CRC=y +CONFIG_ARM_CRYPTO=y +CONFIG_ARM_FLOAT_POINT=y +# CONFIG_GCC_CODE_MODEL_TINY is not set +CONFIG_GCC_CODE_MODEL_SMALL=y +# CONFIG_GCC_CODE_MODEL_LARGE is not set +# end of Compiler configuration + +# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +# CONFIG_MMU_DEBUG_PRINTS is not set +# end of Arm architecture configuration + +CONFIG_MMU_PAGE_SIZE=0x1000 +CONFIG_MAX_XLAT_TABLES=256 +# end of Arch configuration + +# +# Soc configuration +# +CONFIG_TARGET_PHYTIUMPI=y +# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_E2000D is not set +# CONFIG_TARGET_E2000S is not set +# CONFIG_TARGET_FT2004 is not set +# CONFIG_TARGET_D2000 is not set +# CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="phytiumpi" +CONFIG_SOC_CORE_NUM=4 +CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 +CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 +CONFIG_F64BIT_MEMORY_ADDRESS=0x2000000000 +CONFIG_F64BIT_MEMORY_LENGTH=0x800000000 +CONFIG_TARGET_E2000=y +CONFIG_DEFAULT_DEBUG_PRINT_UART1=y +# CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set +# CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set +# end of Soc configuration + +# +# Board Configuration +# +CONFIG_BOARD_NAME="firefly" +# CONFIG_USE_SPI_IOPAD is not set +# CONFIG_USE_GPIO_IOPAD is not set +# CONFIG_USE_CAN_IOPAD is not set +# CONFIG_USE_QSPI_IOPAD is not set +# CONFIG_USE_PWM_IOPAD is not set +# CONFIG_USE_MIO_IOPAD is not set +# CONFIG_USE_TACHO_IOPAD is not set +# CONFIG_USE_UART_IOPAD is not set +# CONFIG_USE_THIRD_PARTY_IOPAD is not set +CONFIG_FIREFLY_DEMO_BOARD=y + +# +# IO mux configuration when board start up +# +# end of IO mux configuration when board start up + +# CONFIG_CUS_DEMO_BOARD is not set + +# +# Build project name +# +CONFIG_TARGET_NAME="lwip_https" +# end of Build project name +# end of Board Configuration + +# +# Sdk common configuration +# +CONFIG_ELOG_LINE_BUF_SIZE=0x100 +# CONFIG_LOG_VERBOS is not set +# CONFIG_LOG_DEBUG is not set +# CONFIG_LOG_INFO is not set +# CONFIG_LOG_WARN is not set +CONFIG_LOG_ERROR=y +# CONFIG_LOG_NONE is not set +# CONFIG_LOG_EXTRA_INFO is not set +# CONFIG_LOG_DISPALY_CORE_NUM is not set +# CONFIG_BOOTUP_DEBUG_PRINTS is not set +CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y +CONFIG_INTERRUPT_ROLE_MASTER=y +# CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set +# end of Sdk common configuration + +# +# Drivers configuration +# +CONFIG_USE_IOMUX=y +# CONFIG_ENABLE_IOCTRL is not set +CONFIG_ENABLE_IOPAD=y +# CONFIG_USE_SPI is not set +# CONFIG_USE_QSPI is not set +CONFIG_USE_SERIAL=y + +# +# Usart Configuration +# +CONFIG_ENABLE_Pl011_UART=y +# end of Usart Configuration + +# CONFIG_USE_GPIO is not set +CONFIG_USE_ETH=y + +# +# Eth Configuration +# +CONFIG_ENABLE_FXMAC=y +# CONFIG_ENABLE_FGMAC is not set +CONFIG_FXMAC_PHY_COMMON=y +# CONFIG_FXMAC_PHY_YT is not set +# end of Eth Configuration + +# CONFIG_USE_CAN is not set +# CONFIG_USE_I2C is not set +# CONFIG_USE_TIMER is not set +# CONFIG_USE_MIO is not set +# CONFIG_USE_SDMMC is not set +# CONFIG_USE_PCIE is not set +# CONFIG_USE_WDT is not set +# CONFIG_USE_DMA is not set +# CONFIG_USE_NAND is not set +# CONFIG_USE_RTC is not set +# CONFIG_USE_SATA is not set +# CONFIG_USE_ADC is not set +# CONFIG_USE_PWM is not set +# CONFIG_USE_IPC is not set +# CONFIG_USE_MEDIA is not set +# CONFIG_USE_SCMI_MHU is not set +# CONFIG_USE_I2S is not set +# CONFIG_USE_I3C is not set +# end of Drivers configuration + +# +# Build setup +# +CONFIG_CHECK_DEPS=y +CONFIG_OUTPUT_BINARY=y + +# +# Optimization options +# +# CONFIG_DEBUG_NOOPT is not set +# CONFIG_DEBUG_CUSTOMOPT is not set +CONFIG_DEBUG_FULLOPT=y +CONFIG_DEBUG_OPT_UNUSED_SECTIONS=y +CONFIG_DEBUG_LINK_MAP=y +# CONFIG_CCACHE is not set +# CONFIG_ARCH_COVERAGE is not set +# CONFIG_LTO_FULL is not set +# end of Optimization options + +# +# Debug options +# +# CONFIG_DEBUG_ENABLE_ALL_WARNING is not set +# CONFIG_WALL_WARNING_ERROR is not set +# CONFIG_STRICT_PROTOTYPES is not set +# CONFIG_DEBUG_SYMBOLS is not set +# CONFIG_FRAME_POINTER is not set +# CONFIG_OUTPUT_ASM_DIS is not set +# CONFIG_ENABLE_WSHADOW is not set +# CONFIG_ENABLE_WUNDEF is not set +CONFIG_DOWNGRADE_DIAG_WARNING=y +# end of Debug options + +# +# Lib +# +CONFIG_USE_COMPILE_CHAIN=y +# CONFIG_USE_NEWLIB is not set +# CONFIG_USE_USER_DEFINED is not set +# end of Lib + +# CONFIG_ENABLE_CXX is not set + +# +# Linker Options +# +CONFIG_DEFAULT_LINKER_SCRIPT=y +# CONFIG_USER_DEFINED_LD is not set +CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 +CONFIG_IMAGE_MAX_LENGTH=0x2000000 +CONFIG_HEAP_SIZE=1 +CONFIG_STACK_SIZE=0x400 +# end of Linker Options +# end of Build setup + +# +# Component Configuration +# + +# +# Freertos Uart Drivers +# +CONFIG_FREERTOS_USE_UART=y +# end of Freertos Uart Drivers + +# +# Freertos Pwm Drivers +# +# CONFIG_FREERTOS_USE_PWM is not set +# end of Freertos Pwm Drivers + +# +# Freertos Qspi Drivers +# +# CONFIG_FREERTOS_USE_QSPI is not set +# end of Freertos Qspi Drivers + +# +# Freertos Wdt Drivers +# +# CONFIG_FREERTOS_USE_WDT is not set +# end of Freertos Wdt Drivers + +# +# Freertos Eth Drivers +# +CONFIG_FREERTOS_USE_XMAC=y +# CONFIG_FREERTOS_USE_GMAC is not set +# end of Freertos Eth Drivers + +# +# Freertos Spim Drivers +# +# CONFIG_FREERTOS_USE_FSPIM is not set +# end of Freertos Spim Drivers + +# +# Freertos DMA Drivers +# +# CONFIG_FREERTOS_USE_FDDMA is not set +# CONFIG_FREERTOS_USE_FGDMA is not set +# end of Freertos DMA Drivers + +# +# Freertos Adc Drivers +# +# CONFIG_FREERTOS_USE_ADC is not set +# end of Freertos Adc Drivers + +# +# Freertos Can Drivers +# +# CONFIG_FREERTOS_USE_CAN is not set +# end of Freertos Can Drivers + +# +# Freertos I2c Drivers +# +# CONFIG_FREERTOS_USE_I2C is not set +# end of Freertos I2c Drivers + +# +# Freertos Mio Drivers +# +# CONFIG_FREERTOS_USE_MIO is not set +# end of Freertos Mio Drivers + +# +# Freertos Timer Drivers +# +# CONFIG_FREERTOS_USE_TIMER is not set +# end of Freertos Timer Drivers + +# +# Freertos Media Drivers +# +# CONFIG_FREERTOS_USE_MEDIA is not set +# end of Freertos Media Drivers + +# +# Freertos I2s Drivers +# +# CONFIG_FREERTOS_USE_I2S is not set +# end of Freertos I2s Drivers +# end of Component Configuration + +# +# Third-party configuration +# +CONFIG_USE_LWIP=y + +# +# LWIP Freertos Port Configuration +# + +# +# LWIP Configuration +# + +# +# LWIP Port Configuration +# +CONFIG_LWIP_FXMAC=y +# CONFIG_LWIP_FGMAC is not set +# CONFIG_LWIP_FSDIF is not set +# end of LWIP Port Configuration + +# CONFIG_LWIP_NO_SYS is not set +CONFIG_LWIP_LOCAL_HOSTNAME="phytium" + +# +# LWIP_APP +# +# CONFIG_USE_LWIP_APP_LWIPERF is not set +# CONFIG_USE_LWIP_APP_TFTP is not set +# CONFIG_USE_LWIP_APP_SNTP is not set +# end of LWIP_APP + +# +# Memory configuration +# +# CONFIG_LWIP_USE_MEM_POOL is not set +CONFIG_LWIP_USE_MEM_HEAP=y +# CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set +CONFIG_MEM_SIZE=2 +CONFIG_MEM_ALIGNMENT=64 +# end of Memory configuration + +# +# Pbuf options +# +CONFIG_PBUF_POOL_BUFSIZE=2 +CONFIG_PBUF_POOL_SIZE=1 +# end of Pbuf options + +# +# ARP +# +CONFIG_ARP_QUEUEING_EN=y +# end of ARP + +# +# IPV4 +# +# CONFIG_USE_IPV4_ONLY is not set +CONFIG_LWIP_IP4_REASSEMBLY=y +CONFIG_LWIP_IP4_FRAG=y +# CONFIG_LWIP_IP_FORWARD is not set +CONFIG_IP_REASS_MAX_PBUFS=32 +# end of IPV4 + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_BROADCAST_PING=y +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_RAW_API_EN=y +CONFIG_LWIP_MAX_RAW_PCBS=16 +CONFIG_LWIP_RAW_RECVMBOX_SIZE=6 +# end of LWIP RAW API + +# +# DHCP +# +CONFIG_LWIP_DHCP_ENABLE=y +# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# end of DHCP + +# +# AUTOIP +# +# CONFIG_LWIP_AUTOIP is not set +# end of AUTOIP + +# +# IGMP +# +CONFIG_LWIP_IGMP_EN=y +# end of IGMP + +# +# DNS +# +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# end of DNS + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# CONFIG_LWIP_NETBUF_RECVINFO is not set +# end of UDP + +# +# TCP +# +CONFIG_LWIP_TCP_WND_DEFAULT=5744 +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5744 +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +# CONFIG_LWIP_WND_SCALE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +# end of TCP + +# +# Network_Interface +# +# CONFIG_LWIP_NETIF_API is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +# end of Network_Interface + +# +# LOOPIF +# +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 +# end of LOOPIF + +# +# SLIPIF +# +# CONFIG_LWIP_SLIP_SUPPORT is not set +# end of SLIPIF + +CONFIG_LWIP_TCPIP_CORE_LOCKING=y + +# +# Socket +# +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# end of Socket + +# CONFIG_LWIP_STATS is not set + +# +# PPP +# +# CONFIG_LWIP_PPP_SUPPORT is not set +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +# end of PPP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +# +# IPV6 +# +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP6_REASSEMBLY is not set +# end of IPV6 + +CONFIG_LWIP_DEBUG=y +# CONFIG_LWIP_DEBUG_ESP_LOG is not set +CONFIG_LWIP_NETIF_DEBUG=y +# CONFIG_LWIP_PBUF_DEBUG is not set +# CONFIG_LWIP_ETHARP_DEBUG is not set +# CONFIG_LWIP_API_LIB_DEBUG is not set +# CONFIG_LWIP_SOCKETS_DEBUG is not set +# CONFIG_LWIP_IP_DEBUG is not set +# CONFIG_LWIP_ICMP_DEBUG is not set +# CONFIG_LWIP_DHCP_STATE_DEBUG is not set +# CONFIG_LWIP_DHCP_DEBUG is not set +# CONFIG_LWIP_IP6_DEBUG is not set +# CONFIG_LWIP_ICMP6_DEBUG is not set +# CONFIG_LWIP_TCP_DEBUG is not set +# CONFIG_LWIP_UDP_DEBUG is not set +# CONFIG_LWIP_SNTP_DEBUG is not set +# CONFIG_LWIP_DNS_DEBUG is not set +# end of LWIP Configuration + +# +# Tcp/ip task resource configuration +# +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_PRIO=6 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +# end of Tcp/ip task resource configuration + +# +# lwip port thread Configuration +# +CONFIG_LWIP_PORT_USE_RECEIVE_THREAD=y +CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE=1024 +CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY=5 +CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD=y +CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE=1024 +CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY=5 +CONFIG_LWIP_PORT_DHCP_THREAD=y +CONFIG_LWIP_PORT_DHCP_STACKSIZE=2048 +CONFIG_LWIP_PORT_DHCP_PRIORITY=5 +# end of lwip port thread Configuration +# end of LWIP Freertos Port Configuration + +CONFIG_USE_MBEDTLS=y + +# +# MBEDTLS Freertos Port Configuration +# +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + +# CONFIG_USE_AMP is not set +# CONFIG_USE_YMODEM is not set +# CONFIG_USE_SFUD is not set +CONFIG_USE_BACKTRACE=y +# CONFIG_USE_FATFS_0_1_4 is not set +CONFIG_USE_TLSF=y +# CONFIG_USE_SPIFFS is not set +# CONFIG_USE_LITTLE_FS is not set +# CONFIG_USE_LVGL is not set +# CONFIG_USE_FREEMODBUS is not set +# CONFIG_USE_CHERRY_USB is not set +# CONFIG_USE_FSL_SDMMC is not set +# CONFIG_USE_FSL_WIFI is not set +# end of Third-party configuration + +# +# FreeRTOS Kernel Configuration +# +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set +CONFIG_FREERTOS_MAX_PRIORITIES=32 +CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 +CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_MINIMAL_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=32 +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y +CONFIG_FREERTOS_USE_TRACE_FACILITY=y +CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS=y +# CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set +CONFIG_FREERTOS_TOTAL_HEAP_SIZE=10240 +CONFIG_FREERTOS_TASK_FPU_SUPPORT=1 +# CONFIG_FREERTOS_USE_POSIX is not set +# end of FreeRTOS Kernel Configuration diff --git a/example/network/lwip_https/sdkconfig.h b/example/network/lwip_https/sdkconfig.h new file mode 100644 index 00000000..aefa7778 --- /dev/null +++ b/example/network/lwip_https/sdkconfig.h @@ -0,0 +1,536 @@ +#ifndef SDK_CONFIG_H__ +#define SDK_CONFIG_H__ + +#define CONFIG_USE_FREERTOS + +/* Arch configuration */ + +#define CONFIG_TARGET_ARMv8 +#define CONFIG_ARCH_NAME "armv8" + +/* Arm architecture configuration */ + +#define CONFIG_ARCH_ARMV8_AARCH64 +/* CONFIG_ARCH_ARMV8_AARCH32 is not set */ + +/* Compiler configuration */ + +#define CONFIG_ARM_GCC_SELECT +/* CONFIG_ARM_CLANG_SELECT is not set */ +#define CONFIG_TOOLCHAIN_NAME "gcc" +#define CONFIG_TARGET_ARMV8_AARCH64 +#define CONFIG_ARCH_EXECUTION_STATE "aarch64" +#define CONFIG_ARM_NEON +#define CONFIG_ARM_CRC +#define CONFIG_ARM_CRYPTO +#define CONFIG_ARM_FLOAT_POINT +/* CONFIG_GCC_CODE_MODEL_TINY is not set */ +#define CONFIG_GCC_CODE_MODEL_SMALL +/* CONFIG_GCC_CODE_MODEL_LARGE is not set */ +/* end of Compiler configuration */ +/* CONFIG_BOOT_WITH_FLUSH_CACHE is not set */ +/* CONFIG_MMU_DEBUG_PRINTS is not set */ +/* end of Arm architecture configuration */ +#define CONFIG_MMU_PAGE_SIZE 0x1000 +#define CONFIG_MAX_XLAT_TABLES 256 +/* end of Arch configuration */ + +/* Soc configuration */ + +#define CONFIG_TARGET_PHYTIUMPI +/* CONFIG_TARGET_E2000Q is not set */ +/* CONFIG_TARGET_E2000D is not set */ +/* CONFIG_TARGET_E2000S is not set */ +/* CONFIG_TARGET_FT2004 is not set */ +/* CONFIG_TARGET_D2000 is not set */ +/* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ +#define CONFIG_SOC_NAME "phytiumpi" +#define CONFIG_SOC_CORE_NUM 4 +#define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 +#define CONFIG_F32BIT_MEMORY_LENGTH 0x80000000 +#define CONFIG_F64BIT_MEMORY_ADDRESS 0x2000000000 +#define CONFIG_F64BIT_MEMORY_LENGTH 0x800000000 +#define CONFIG_TARGET_E2000 +#define CONFIG_DEFAULT_DEBUG_PRINT_UART1 +/* CONFIG_DEFAULT_DEBUG_PRINT_UART0 is not set */ +/* CONFIG_DEFAULT_DEBUG_PRINT_UART2 is not set */ +/* end of Soc configuration */ + +/* Board Configuration */ + +#define CONFIG_BOARD_NAME "firefly" +/* CONFIG_USE_SPI_IOPAD is not set */ +/* CONFIG_USE_GPIO_IOPAD is not set */ +/* CONFIG_USE_CAN_IOPAD is not set */ +/* CONFIG_USE_QSPI_IOPAD is not set */ +/* CONFIG_USE_PWM_IOPAD is not set */ +/* CONFIG_USE_MIO_IOPAD is not set */ +/* CONFIG_USE_TACHO_IOPAD is not set */ +/* CONFIG_USE_UART_IOPAD is not set */ +/* CONFIG_USE_THIRD_PARTY_IOPAD is not set */ +#define CONFIG_FIREFLY_DEMO_BOARD + +/* IO mux configuration when board start up */ + +/* end of IO mux configuration when board start up */ +/* CONFIG_CUS_DEMO_BOARD is not set */ + +/* Build project name */ + +#define CONFIG_TARGET_NAME "lwip_https" +/* end of Build project name */ +/* end of Board Configuration */ + +/* Sdk common configuration */ + +#define CONFIG_ELOG_LINE_BUF_SIZE 0x100 +/* CONFIG_LOG_VERBOS is not set */ +/* CONFIG_LOG_DEBUG is not set */ +/* CONFIG_LOG_INFO is not set */ +/* CONFIG_LOG_WARN is not set */ +#define CONFIG_LOG_ERROR +/* CONFIG_LOG_NONE is not set */ +/* CONFIG_LOG_EXTRA_INFO is not set */ +/* CONFIG_LOG_DISPALY_CORE_NUM is not set */ +/* CONFIG_BOOTUP_DEBUG_PRINTS is not set */ +#define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG +#define CONFIG_INTERRUPT_ROLE_MASTER +/* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ +/* end of Sdk common configuration */ + +/* Drivers configuration */ + +#define CONFIG_USE_IOMUX +/* CONFIG_ENABLE_IOCTRL is not set */ +#define CONFIG_ENABLE_IOPAD +/* CONFIG_USE_SPI is not set */ +/* CONFIG_USE_QSPI is not set */ +#define CONFIG_USE_SERIAL + +/* Usart Configuration */ + +#define CONFIG_ENABLE_Pl011_UART +/* end of Usart Configuration */ +/* CONFIG_USE_GPIO is not set */ +#define CONFIG_USE_ETH + +/* Eth Configuration */ + +#define CONFIG_ENABLE_FXMAC +/* CONFIG_ENABLE_FGMAC is not set */ +#define CONFIG_FXMAC_PHY_COMMON +/* CONFIG_FXMAC_PHY_YT is not set */ +/* end of Eth Configuration */ +/* CONFIG_USE_CAN is not set */ +/* CONFIG_USE_I2C is not set */ +/* CONFIG_USE_TIMER is not set */ +/* CONFIG_USE_MIO is not set */ +/* CONFIG_USE_SDMMC is not set */ +/* CONFIG_USE_PCIE is not set */ +/* CONFIG_USE_WDT is not set */ +/* CONFIG_USE_DMA is not set */ +/* CONFIG_USE_NAND is not set */ +/* CONFIG_USE_RTC is not set */ +/* CONFIG_USE_SATA is not set */ +/* CONFIG_USE_ADC is not set */ +/* CONFIG_USE_PWM is not set */ +/* CONFIG_USE_IPC is not set */ +/* CONFIG_USE_MEDIA is not set */ +/* CONFIG_USE_SCMI_MHU is not set */ +/* CONFIG_USE_I2S is not set */ +/* CONFIG_USE_I3C is not set */ +/* end of Drivers configuration */ + +/* Build setup */ + +#define CONFIG_CHECK_DEPS +#define CONFIG_OUTPUT_BINARY + +/* Optimization options */ + +/* CONFIG_DEBUG_NOOPT is not set */ +/* CONFIG_DEBUG_CUSTOMOPT is not set */ +#define CONFIG_DEBUG_FULLOPT +#define CONFIG_DEBUG_OPT_UNUSED_SECTIONS +#define CONFIG_DEBUG_LINK_MAP +/* CONFIG_CCACHE is not set */ +/* CONFIG_ARCH_COVERAGE is not set */ +/* CONFIG_LTO_FULL is not set */ +/* end of Optimization options */ + +/* Debug options */ + +/* CONFIG_DEBUG_ENABLE_ALL_WARNING is not set */ +/* CONFIG_WALL_WARNING_ERROR is not set */ +/* CONFIG_STRICT_PROTOTYPES is not set */ +/* CONFIG_DEBUG_SYMBOLS is not set */ +/* CONFIG_FRAME_POINTER is not set */ +/* CONFIG_OUTPUT_ASM_DIS is not set */ +/* CONFIG_ENABLE_WSHADOW is not set */ +/* CONFIG_ENABLE_WUNDEF is not set */ +#define CONFIG_DOWNGRADE_DIAG_WARNING +/* end of Debug options */ + +/* Lib */ + +#define CONFIG_USE_COMPILE_CHAIN +/* CONFIG_USE_NEWLIB is not set */ +/* CONFIG_USE_USER_DEFINED is not set */ +/* end of Lib */ +/* CONFIG_ENABLE_CXX is not set */ + +/* Linker Options */ + +#define CONFIG_DEFAULT_LINKER_SCRIPT +/* CONFIG_USER_DEFINED_LD is not set */ +#define CONFIG_IMAGE_LOAD_ADDRESS 0x80100000 +#define CONFIG_IMAGE_MAX_LENGTH 0x2000000 +#define CONFIG_HEAP_SIZE 1 +#define CONFIG_STACK_SIZE 0x400 +/* end of Linker Options */ +/* end of Build setup */ + +/* Component Configuration */ + +/* Freertos Uart Drivers */ + +#define CONFIG_FREERTOS_USE_UART +/* end of Freertos Uart Drivers */ + +/* Freertos Pwm Drivers */ + +/* CONFIG_FREERTOS_USE_PWM is not set */ +/* end of Freertos Pwm Drivers */ + +/* Freertos Qspi Drivers */ + +/* CONFIG_FREERTOS_USE_QSPI is not set */ +/* end of Freertos Qspi Drivers */ + +/* Freertos Wdt Drivers */ + +/* CONFIG_FREERTOS_USE_WDT is not set */ +/* end of Freertos Wdt Drivers */ + +/* Freertos Eth Drivers */ + +#define CONFIG_FREERTOS_USE_XMAC +/* CONFIG_FREERTOS_USE_GMAC is not set */ +/* end of Freertos Eth Drivers */ + +/* Freertos Spim Drivers */ + +/* CONFIG_FREERTOS_USE_FSPIM is not set */ +/* end of Freertos Spim Drivers */ + +/* Freertos DMA Drivers */ + +/* CONFIG_FREERTOS_USE_FDDMA is not set */ +/* CONFIG_FREERTOS_USE_FGDMA is not set */ +/* end of Freertos DMA Drivers */ + +/* Freertos Adc Drivers */ + +/* CONFIG_FREERTOS_USE_ADC is not set */ +/* end of Freertos Adc Drivers */ + +/* Freertos Can Drivers */ + +/* CONFIG_FREERTOS_USE_CAN is not set */ +/* end of Freertos Can Drivers */ + +/* Freertos I2c Drivers */ + +/* CONFIG_FREERTOS_USE_I2C is not set */ +/* end of Freertos I2c Drivers */ + +/* Freertos Mio Drivers */ + +/* CONFIG_FREERTOS_USE_MIO is not set */ +/* end of Freertos Mio Drivers */ + +/* Freertos Timer Drivers */ + +/* CONFIG_FREERTOS_USE_TIMER is not set */ +/* end of Freertos Timer Drivers */ + +/* Freertos Media Drivers */ + +/* CONFIG_FREERTOS_USE_MEDIA is not set */ +/* end of Freertos Media Drivers */ + +/* Freertos I2s Drivers */ + +/* CONFIG_FREERTOS_USE_I2S is not set */ +/* end of Freertos I2s Drivers */ +/* end of Component Configuration */ + +/* Third-party configuration */ + +#define CONFIG_USE_LWIP + +/* LWIP Freertos Port Configuration */ + +/* LWIP Configuration */ + +/* LWIP Port Configuration */ + +#define CONFIG_LWIP_FXMAC +/* CONFIG_LWIP_FGMAC is not set */ +/* CONFIG_LWIP_FSDIF is not set */ +/* end of LWIP Port Configuration */ +/* CONFIG_LWIP_NO_SYS is not set */ +#define CONFIG_LWIP_LOCAL_HOSTNAME "phytium" + +/* LWIP_APP */ + +/* CONFIG_USE_LWIP_APP_LWIPERF is not set */ +/* CONFIG_USE_LWIP_APP_TFTP is not set */ +/* CONFIG_USE_LWIP_APP_SNTP is not set */ +/* end of LWIP_APP */ + +/* Memory configuration */ + +/* CONFIG_LWIP_USE_MEM_POOL is not set */ +#define CONFIG_LWIP_USE_MEM_HEAP +/* CONFIG_LWIP_USE_MEM_HEAP_DEBUG is not set */ +#define CONFIG_MEM_SIZE 2 +#define CONFIG_MEM_ALIGNMENT 64 +/* end of Memory configuration */ + +/* Pbuf options */ + +#define CONFIG_PBUF_POOL_BUFSIZE 2 +#define CONFIG_PBUF_POOL_SIZE 1 +/* end of Pbuf options */ + +/* ARP */ + +#define CONFIG_ARP_QUEUEING_EN +/* end of ARP */ + +/* IPV4 */ + +/* CONFIG_USE_IPV4_ONLY is not set */ +#define CONFIG_LWIP_IP4_REASSEMBLY +#define CONFIG_LWIP_IP4_FRAG +/* CONFIG_LWIP_IP_FORWARD is not set */ +#define CONFIG_IP_REASS_MAX_PBUFS 32 +/* end of IPV4 */ + +/* ICMP */ + +#define CONFIG_LWIP_ICMP +#define CONFIG_LWIP_MULTICAST_PING +#define CONFIG_LWIP_BROADCAST_PING +/* end of ICMP */ + +/* LWIP RAW API */ + +#define CONFIG_LWIP_RAW_API_EN +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_RAW_RECVMBOX_SIZE 6 +/* end of LWIP RAW API */ + +/* DHCP */ + +#define CONFIG_LWIP_DHCP_ENABLE +/* CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set */ +/* CONFIG_LWIP_DHCP_GET_NTP_SRV is not set */ +/* CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set */ +/* CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set */ +#define CONFIG_LWIP_DHCP_OPTIONS_LEN 68 +#define CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID +/* end of DHCP */ + +/* AUTOIP */ + +/* CONFIG_LWIP_AUTOIP is not set */ +/* end of AUTOIP */ + +/* IGMP */ + +#define CONFIG_LWIP_IGMP_EN +/* end of IGMP */ + +/* DNS */ + +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES +/* end of DNS */ + +/* UDP */ + +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +/* CONFIG_LWIP_NETBUF_RECVINFO is not set */ +/* end of UDP */ + +/* TCP */ + +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 12 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ +/* CONFIG_LWIP_TCP_SACK_OUT is not set */ +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS +/* CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set */ +/* CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set */ +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +/* CONFIG_LWIP_WND_SCALE is not set */ +#define CONFIG_LWIP_TCP_RTO_TIME 1500 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +/* end of TCP */ + +/* Network_Interface */ + +/* CONFIG_LWIP_NETIF_API is not set */ +/* CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set */ +/* end of Network_Interface */ + +/* LOOPIF */ + +#define CONFIG_LWIP_NETIF_LOOPBACK +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +/* end of LOOPIF */ + +/* SLIPIF */ + +/* CONFIG_LWIP_SLIP_SUPPORT is not set */ +/* end of SLIPIF */ +#define CONFIG_LWIP_TCPIP_CORE_LOCKING + +/* Socket */ + +#define CONFIG_LWIP_MAX_SOCKETS 10 +/* CONFIG_LWIP_SO_LINGER is not set */ +#define CONFIG_LWIP_SO_REUSE +#define CONFIG_LWIP_SO_REUSE_RXTOALL +/* end of Socket */ +/* CONFIG_LWIP_STATS is not set */ + +/* PPP */ + +/* CONFIG_LWIP_PPP_SUPPORT is not set */ +#define CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE 3 +#define CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS 5 +/* end of PPP */ + +/* Checksums */ + +/* CONFIG_LWIP_CHECKSUM_CHECK_IP is not set */ +/* CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set */ +#define CONFIG_LWIP_CHECKSUM_CHECK_ICMP +/* end of Checksums */ + +/* IPV6 */ + +#define CONFIG_LWIP_IPV6 +/* CONFIG_LWIP_IPV6_AUTOCONFIG is not set */ +#define CONFIG_LWIP_IPV6_NUM_ADDRESSES 3 +/* CONFIG_LWIP_IPV6_FORWARD is not set */ +#define CONFIG_LWIP_IP6_FRAG +/* CONFIG_LWIP_IP6_REASSEMBLY is not set */ +/* end of IPV6 */ +#define CONFIG_LWIP_DEBUG +/* CONFIG_LWIP_DEBUG_ESP_LOG is not set */ +#define CONFIG_LWIP_NETIF_DEBUG +/* CONFIG_LWIP_PBUF_DEBUG is not set */ +/* CONFIG_LWIP_ETHARP_DEBUG is not set */ +/* CONFIG_LWIP_API_LIB_DEBUG is not set */ +/* CONFIG_LWIP_SOCKETS_DEBUG is not set */ +/* CONFIG_LWIP_IP_DEBUG is not set */ +/* CONFIG_LWIP_ICMP_DEBUG is not set */ +/* CONFIG_LWIP_DHCP_STATE_DEBUG is not set */ +/* CONFIG_LWIP_DHCP_DEBUG is not set */ +/* CONFIG_LWIP_IP6_DEBUG is not set */ +/* CONFIG_LWIP_ICMP6_DEBUG is not set */ +/* CONFIG_LWIP_TCP_DEBUG is not set */ +/* CONFIG_LWIP_UDP_DEBUG is not set */ +/* CONFIG_LWIP_SNTP_DEBUG is not set */ +/* CONFIG_LWIP_DNS_DEBUG is not set */ +/* end of LWIP Configuration */ + +/* Tcp/ip task resource configuration */ + +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_PRIO 6 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +/* end of Tcp/ip task resource configuration */ + +/* lwip port thread Configuration */ + +#define CONFIG_LWIP_PORT_USE_RECEIVE_THREAD +#define CONFIG_LWIP_PORT_RECEIVE_THREAD_STACKSIZE 1024 +#define CONFIG_LWIP_PORT_RECEIVE_THREAD_PRIORITY 5 +#define CONFIG_LWIP_PORT_USE_LINK_DETECT_THREAD +#define CONFIG_LWIP_PORT_LINK_DETECT_STACKSIZE 1024 +#define CONFIG_LWIP_PORT_LINK_DETECT_PRIORITY 5 +#define CONFIG_LWIP_PORT_DHCP_THREAD +#define CONFIG_LWIP_PORT_DHCP_STACKSIZE 2048 +#define CONFIG_LWIP_PORT_DHCP_PRIORITY 5 +/* end of lwip port thread Configuration */ +/* end of LWIP Freertos Port Configuration */ +#define CONFIG_USE_MBEDTLS + +/* MBEDTLS Freertos Port Configuration */ + +#define CONFIG_USE_LETTER_SHELL + +/* Letter Shell Configuration */ + +#define CONFIG_LS_PL011_UART +#define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ +/* end of Letter Shell Configuration */ +/* CONFIG_USE_AMP is not set */ +/* CONFIG_USE_YMODEM is not set */ +/* CONFIG_USE_SFUD is not set */ +#define CONFIG_USE_BACKTRACE +/* CONFIG_USE_FATFS_0_1_4 is not set */ +#define CONFIG_USE_TLSF +/* CONFIG_USE_SPIFFS is not set */ +/* CONFIG_USE_LITTLE_FS is not set */ +/* CONFIG_USE_LVGL is not set */ +/* CONFIG_USE_FREEMODBUS is not set */ +/* CONFIG_USE_CHERRY_USB is not set */ +/* CONFIG_USE_FSL_SDMMC is not set */ +/* CONFIG_USE_FSL_WIFI is not set */ +/* end of Third-party configuration */ + +/* FreeRTOS Kernel Configuration */ + +#define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER +#define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ +#define CONFIG_FREERTOS_MAX_PRIORITIES 32 +#define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 +#define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_MINIMAL_TASK_STACKSIZE 1024 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 32 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS +#define CONFIG_FREERTOS_USE_TRACE_FACILITY +#define CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS +/* CONFIG_FREERTOS_USE_TICKLESS_IDLE is not set */ +#define CONFIG_FREERTOS_TOTAL_HEAP_SIZE 10240 +#define CONFIG_FREERTOS_TASK_FPU_SUPPORT 1 +/* CONFIG_FREERTOS_USE_POSIX is not set */ +/* end of FreeRTOS Kernel Configuration */ + +#endif diff --git a/example/network/lwip_https/src/cmd_https.c b/example/network/lwip_https/src/cmd_https.c new file mode 100644 index 00000000..204ae2a8 --- /dev/null +++ b/example/network/lwip_https/src/cmd_https.c @@ -0,0 +1,91 @@ +/* + * Copyright : (C) 2023 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program 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 Phytium Public License for more details. + * + * + * FilePath: cmd_https.c + * Created Date: 2024-9-29 11:06:40 + * Last Modified: 2024-09-29 15:52:43 + * Description: This file is for https example cmd catalogue. + * + * Modify History: + * Ver Who Date Changes + * ----- ---------- -------- --------------------------------- + * 1.0 huangjin 2024/9/29 first release + */ + +#include +#include + +#include "sdkconfig.h" +#ifndef SDK_CONFIG_H__ + #warning "Please include sdkconfig.h" +#endif + +#ifdef CONFIG_USE_LETTER_SHELL +#include "shell.h" +#include "strto.h" + +#include "https_example.h" + +#define EXAMPLE_IDLE 0 +#define HTTPS_EXAMPLE_RUNNING 1 + +static u32 init_flag_mask = EXAMPLE_IDLE; + +static void HttpsExampleCheckState(void) +{ + switch(init_flag_mask) + { + case HTTPS_EXAMPLE_RUNNING: + printf("Https example is running, we need to deinitialize it first! \r\n"); + HttpsTestDeinit(); + init_flag_mask = EXAMPLE_IDLE; + break; + default: + break; + } +} + +/* usage info function for https example */ +static void HttpsExampleUsage(void) +{ + printf("Usage:\r\n"); + printf("lwip https\r\n"); + printf("-- run https example to initialize mac controller\r\n"); +} + +/* entry function for https example */ +static int HttpsExampleEntry(int argc, char *argv[]) +{ + int ret = 0; + + /* check input args of example, exit if invaild */ + if (argc < 2) + { + HttpsExampleUsage(); + return -1; + } + + /* parser example input args and run example */ + if (!strcmp(argv[1], "https")) + { + HttpsExampleCheckState(); + ret = FFreeRTOSHttpsTaskCreate(); + init_flag_mask = HTTPS_EXAMPLE_RUNNING; + } + + return ret; +} + +/* register command for https example */ +SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), lwip, HttpsExampleEntry, https example); +#endif \ No newline at end of file diff --git a/example/network/lwip_https/src/https_example.c b/example/network/lwip_https/src/https_example.c new file mode 100644 index 00000000..ecf53304 --- /dev/null +++ b/example/network/lwip_https/src/https_example.c @@ -0,0 +1,448 @@ +/* + * Copyright : (C) 2023 Phytium Information Technology, Inc. + * All Rights Reserved. + * + * This program is OPEN SOURCE software: you can redistribute it and/or modify it + * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd, + * either version 1.0 of the License, or (at your option) any later version. + * + * This program 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 Phytium Public License for more details. + * + * + * FilePath: https_example.c + * Created Date: 2024-9-29 11:12:04 + * Last Modified: 2024-09-29 15:53:23 + * Description: This file is for https example function implementation. + * + * Modify History: + * Ver Who Date Changes + * ----- ---------- -------- --------------------------------- + * 1.0 huangjin 2024/9/29 first release + */ + +#include +#include +#include "strto.h" +#include "sdkconfig.h" +#include "ftypes.h" +#include "fassert.h" +#include "fparameters.h" +#include "eth_board.h" +#ifndef SDK_CONFIG_H__ + #error "Please include sdkconfig.h first" +#endif +#include "FreeRTOS.h" + +#include "lwip_port.h" +#include "lwip/ip4_addr.h" +#include "lwip/init.h" +#include "netif/ethernet.h" +#include "lwip/netif.h" +#include "lwip/tcpip.h" +#include "lwip/inet.h" + +/* mbedtls头文件 */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/net_sockets.h" +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "mbedtls/certs.h" + +#include "tls_certificate.h" +#include "tls_net.h" + +/* https server 参数 */ +#define SERVER_NAME "localhost" +#define SERVER_IP "192.168.4.50" +#define SERVER_PORT "4433" + +#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" + +#define ETH_NAME_PREFIX 'e' + +#define CONFIG_DEFAULT_INIT(config,driver_config,instance_id,interface_type) \ + .config.magic_code = LWIP_PORT_CONFIG_MAGIC_CODE, \ + .config.driver_type = driver_config, \ + .config.mac_instance = instance_id, \ + .config.mii_interface = interface_type, \ + .config.autonegotiation = 1, \ + .config.phy_speed = LWIP_PORT_SPEED_1000M, \ + .config.phy_duplex = LWIP_PORT_FULL_DUPLEX, \ + .config.capability = LWIP_PORT_MODE_NAIVE, + +#define TIMER_OUT (pdMS_TO_TICKS(5000UL)) + +enum +{ + HTTPS_EXAMPLE_SUCCESS = 0, + HTTPS_EXAMPLE_UNKNOWN_STATE = 1, + HTTPS_EXAMPLE_INIT_FAILURE = 2, +}; +static QueueHandle_t xQueue = NULL; + +typedef struct +{ + UserConfig lwip_mac_config; + u32 dhcp_en; + char* ipaddr; + char* netmask; + char* gw; + unsigned char mac_address[6]; + struct netif netif; +} BoardMacConfig; + + + static BoardMacConfig board_mac_config[MAC_NUM] = + { + #if defined(MAC_NUM0) + { + CONFIG_DEFAULT_INIT(lwip_mac_config,MAC_NUM0_LWIP_PORT_TYPE,MAC_NUM0_CONTROLLER,MAC_NUM0_MII_INTERFACE) + .dhcp_en=0, + .ipaddr="192.168.4.10", + .gw="192.168.4.1", + .netmask="255.255.255.0", + .mac_address={0x98, 0x0e, 0x24, 0x00, 0x11, 0x0}, + }, + #endif + #if defined(MAC_NUM1) + { + CONFIG_DEFAULT_INIT(lwip_mac_config,MAC_NUM1_LWIP_PORT_TYPE,MAC_NUM1_CONTROLLER,MAC_NUM1_MII_INTERFACE) + .dhcp_en=0, + .ipaddr="192.168.4.11", + .gw="192.168.4.1", + .netmask="255.255.255.0", + .mac_address={0x98, 0x0e, 0x24, 0x00, 0x11, 0x1}, + }, + #endif +}; + + +static void my_debug( void *ctx, int level, const char *file, int line, const char *str ) +{ + ((void) level); + fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str ); +} + +static void SetIP(ip_addr_t* ipaddr,ip_addr_t* gw,ip_addr_t* netmask,u32 mac_id) +{ + if(inet_aton(board_mac_config[mac_id].ipaddr,ipaddr)==0) + printf("The addr of ipaddr is wrong\r\n"); + if(inet_aton(board_mac_config[mac_id].gw,gw)==0) + printf("The addr of gw is wrong\r\n"); + if(inet_aton(board_mac_config[mac_id].netmask,netmask)==0) + printf("The addr of netmask is wrong\r\n"); +} + +static int entropy_source(void *data, uint8_t *output, size_t len, size_t *olen) +{ + uint32_t seed; + + seed = rand(); + + if ( len > sizeof(seed) ) + { + len = sizeof(seed); + } + memcpy(output, &seed, len); + + *olen = len; + return 0; +} + +void HttpsInitTask(void) +{ + int task_res = HTTPS_EXAMPLE_SUCCESS; + + /* MAC初始化 */ + for (int i = 0; i < MAC_NUM; i++) + { + struct netif *netif_p = NULL; + ip_addr_t ipaddr,netmask, gw; + board_mac_config[i].lwip_mac_config.name[0] = ETH_NAME_PREFIX; + itoa(board_mac_config[i].lwip_mac_config.mac_instance, &(board_mac_config[i].lwip_mac_config.name[1]), 10); + + /* mac ip addr set: char* -> ip_addr_t */ + SetIP(&ipaddr,&gw,&netmask,i); + + netif_p= &board_mac_config[i].netif; + /* Add network interface to the netif_list, and set it as default */ + if (!LwipPortAdd(netif_p, &ipaddr, &netmask, &gw, board_mac_config[i].mac_address, (UserConfig *)&board_mac_config[i])) + { + printf("Error adding N/W interface %d.\n\r",board_mac_config[i].lwip_mac_config.mac_instance); + task_res = HTTPS_EXAMPLE_INIT_FAILURE; + goto exit; + } + printf("LwipPortAdd mac_instance %d is over.\n\r",board_mac_config[i].lwip_mac_config.mac_instance); + + netif_set_default(netif_p); + + if (netif_is_link_up(netif_p)) + { + /* 当netif完全配置好时,必须调用该函数 */ + netif_set_up(netif_p); + if (board_mac_config[i].dhcp_en == 1) + { + LwipPortDhcpSet(netif_p, TRUE); + } + } + else + { + /* 当netif链接关闭时,必须调用该函数 */ + netif_set_down(netif_p); + } + } + printf("Network setup complete.\n"); + + /* 进行Https测试 */ + printf("\n . Start Https test!"); + int ret, len = 0; + uint32_t flags; + uint8_t buf[256]; + + const char *pers = "tls_client"; + + /* 初始化数据 */ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_x509_crt cacert; + mbedtls_ssl_config conf; + mbedtls_net_context server_fd; + + mbedtls_net_init(&server_fd); + mbedtls_ssl_init(&ssl); + mbedtls_x509_crt_init(&cacert); + mbedtls_ssl_config_init(&conf); + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + /* 添加熵源接口,设置熵源属性 */ + printf("\n . Seeding the random number generator..."); + mbedtls_entropy_add_source(&entropy, + entropy_source, + NULL, + MBEDTLS_ENTROPY_MAX_GATHER, //熵源可用阈值,随机数达到阈值时熵源才被使用 + MBEDTLS_ENTROPY_SOURCE_STRONG); //强熵源,一般是硬件真随机数生成器 + if((task_res = mbedtls_ctr_drbg_seed(&ctr_drbg, + mbedtls_entropy_func, + &entropy, + (const unsigned char *)pers, + strlen(pers))) != 0) + { + printf("failed\n ! mbedtls_ctr_drbg_seed returned %d\n", task_res); + goto exit; + } + printf("ok\n"); + + /* 初始化证书 */ + printf( " . Loading the CA root certificate ..." ); + task_res = mbedtls_x509_crt_parse( &cacert, + (const unsigned char *) mbedtls_test_cas_pem, + mbedtls_test_cas_pem_len ); + if( task_res < 0 ) + { + printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -task_res ); + goto exit; + } + printf( " ok (%d skipped)\n", task_res ); + + /* 开始连接 */ + printf( " . Connecting to tcp/%s/%s...", SERVER_IP, SERVER_PORT ); + if( ( task_res = mbedtls_net_connect( &server_fd, + SERVER_IP, + SERVER_PORT, + MBEDTLS_NET_PROTO_TCP ) ) != 0 ) + { + printf( " failed\n ! mbedtls_net_connect returned %d\n\n", task_res ); + goto exit; + } + printf( " ok\n" ); + + /* TLS握手过程的初始化 */ + printf( " . Setting up the SSL/TLS structure..." ); + if( ( task_res = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", task_res ); + goto exit; + } + printf( " ok\n" ); + + /* 配置认证模式、CA证书链、随机数生成器、调试回调、设置TLS结构体、设置服务器主机名和设置TLS连接的底层W/R操作 */ + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + if( ( task_res = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", task_res ); + goto exit; + } + if( ( task_res = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) + { + printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", task_res ); + goto exit; + } + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + /* TLS握手 */ + printf( " . Performing the SSL/TLS handshake..." ); + while( ( task_res = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( task_res != MBEDTLS_ERR_SSL_WANT_READ && task_res != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -task_res ); + goto exit; + } + } + printf( " ok\n" ); + + /* 验证服务器证书 */ + printf( " . Verifying peer X.509 certificate..." ); + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + printf( "%s\n", vrfy_buf ); + } + else + { + printf( " ok\n" ); + } + + /* 编写GET请求 */ + printf( " > Write to server:" ); + len = sprintf( (char *) buf, GET_REQUEST ); + while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + { + printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto exit; + } + } + len = ret; + printf( " %d bytes written\n\n%s", len, (char *) buf ); + + /* 读取HTTPS响应 */ + printf( " < Read from server:" ); + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + continue; + + if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) + break; + + if( ret < 0 ) + { + printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); + break; + } + + if( ret == 0 ) + { + printf( "\n\nEOF\n\n" ); + break; + } + + len = ret; + printf( " %d bytes read\n\n%s", len, (char *) buf ); + } + while( 1 ); + + mbedtls_ssl_close_notify( &ssl ); + + +exit: + mbedtls_net_free( &server_fd ); + mbedtls_x509_crt_free( &cacert ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + + xQueueSend(xQueue, &task_res, 0); + vTaskDelete(NULL); +} + +int FFreeRTOSHttpsTaskCreate(void) +{ + BaseType_t xReturn = pdPASS; /* 定义一个创建信息返回值,默认为 pdPASS */ + int ret = HTTPS_EXAMPLE_UNKNOWN_STATE; + + xQueue = xQueueCreate(1, sizeof(int)); /* 创建消息队列 */ + if (xQueue == NULL) + { + printf("xQueue create failed.\r\n"); + goto exit; + } + + xReturn = xTaskCreate((TaskFunction_t)HttpsInitTask, /* 任务入口函数 */ + (const char *)"HttpsInitTask", /* 任务名字 */ + 4096, /* 任务栈大小 */ + NULL, /* 任务入口函数参数 */ + (UBaseType_t)configMAX_PRIORITIES - 1, /* 任务的优先级 */ + NULL); /* 任务控制块指针 */ + if (xReturn == pdFAIL) + { + printf("xTaskCreate HttpsInitTask failed.\r\n"); + goto exit; + } + + xReturn = xQueueReceive(xQueue, &ret, TIMER_OUT); + if (xReturn == pdFAIL) + { + printf("xQueue receive timeout.\r\n"); + goto exit; + } + +exit: + if (xQueue != NULL) + { + vQueueDelete(xQueue); + } + + if (ret != HTTPS_EXAMPLE_SUCCESS) + { + printf("%s@%d: Https example [failure], ret = %d\r\n", __func__, __LINE__, ret); + return ret; + } + else + { + printf("%s@%d: Https example [success].\r\n", __func__, __LINE__); + return ret; + } +} + +void HttpsTestDeinit(void) +{ + for (int i = 0; i < MAC_NUM; i++) + { + struct netif *netif_p = NULL; + netif_p = &board_mac_config[i].netif; + vPortEnterCritical(); + LwipPortStop(netif_p,board_mac_config[i].dhcp_en); + vPortExitCritical(); + } +} \ No newline at end of file diff --git a/example/network/lwip_https/tools/ssl_server b/example/network/lwip_https/tools/ssl_server new file mode 100644 index 0000000000000000000000000000000000000000..35fc3ad1977753cbf493de7de0f833852f96859f GIT binary patch literal 566672 zcmeFadwf*Y)yF*{L57=WRM1$pj5^j(Z;65?k5V&`$QhkzRL}q_K`sX65+TueK?9RW zPRG&IYihlut=6<^O>Kn?C{6$&SkVYxqP7z8cE+egREQwv{jI&%nVc-m`+h#}-{pDg zoc%p(@4fcgYp;DdXC}87hR++6mgaH(rF(wkp;Y!_P4f9h{Uct!@_6z+xt@{uuirDq za}a0-{+G{p5N=XN%e3^9dGoMFm>~TIF4e68e4fLUQ%rRu+_&+oSAQk_qCK6NKs<%VJUf0ktF20EYad}N#M=|faS-PelGLS29M0@j1| zq|zu~#~-wO$5Z`3yV(%Vr(;jjk^Yy<_LQG~+@pVf^DolmNR{$2V> z#hm{?^%Zlz{3x{&ej`2u$0+P^KArk5Mn0WG-~a#mFPqbI3D-AJKlr#GoKH5d=d=a$ zuRe3!X$$6@vS9wA%BoYUa?d>F%yFkKU3}{4s%p}U>L72JeBo3N`Yl0>&8Yff6sPHa z;oQ4N&7XAZ2^+r4`)gqP8Bf1+>p6p*GN?|Hp?{R0hm1fS)@+Ih6y*A3T7b z+Xg77ZUFx70Q{~2_>ckWy>I~el>_Mi>HypvpqxihuOIj1zup1L88iTopn#wA|CQvnO9$W+2dMYe0pv#yAb;cl@|y?X_YF|ahXe4v1MsH@;L8W7chvy$jRWw~0r;;5 zDF37Z_`(6o`EmgHX9n<}hX;^2_@Bzx-4}OT}C{JgzUSBxtffrHE zak%%Bf0z$v)AVoAeI?vpy`4yhoix(}L zJG%mR=FOSAphDf4yHKRJ&063oudG-Kv85HWW?x5QGw02k zujuTuSxY<%<}a<7yU4S2?gA?9nuQhf7tZy}yJjx(%$~Ji!Q$DTr4>sSKmusioH@{9 z-eS+fxeJ#>X1xw6*08<)(lKwFp0oi&FPq?Rw9H)qyO$VF0n>llK)vTHG=ELUmZ=UN}dec%eAeB#&+Hmt` zFREC8EYQokDhTV6bnr$nmK3glDXHAUo4qYG-<)&MRTXj zx_ZG}=yT1&#fw;x3%u*RbQqqWvg|1Se8x}VZMqH|N;gZjx0QsoZ8x?0Mn ztM!~io!ZkpLp&I2&UV35_qzwMyz_d-BYx1j@`(BKM|vQW&*}Tr{ewK`bNYUj9_*RQ z=}}5P!&A!X%3sVMN?Kma>53yMJ;-wd()7>Sk2vGrSFU*v?^7J!&ig>`b^YT+;$poI z$`#yZUM9Hj5-r~#crNoc!AqI<2wulLYe9c~nwggf-od<1aL=V$pBBNhnA?IEGtXSu zzus!*rr^!Ys|4?4-Xyqhiq@w?@LcBJMg8k7Wu7Z|9rH55o0&HV-od<0aL-h&PmkbP z%(E8v*Qc0yiQv`D>jZCR-XeG>b6arVWm=!i^8WSaGB*V;VO}M8HS;FHo0xY9-p<^6 zegArUnCA-azg+8CCio?DG;a{xWcfD17qfhi;AJeIwWPm3b<9fyZ(&|1xXrvpa9@em z(-u6JdFImo^_DR=1#e(pC3u2)li;1qI|TPk)B1QT`q%4co-6pBY_~GO|LWLZ@J-Cy z1mEGSUvD;-pDTC?^D@D!nKuaD#Jo-LcIG{T_b|_@>aUM~2HRioV&-*% zS2J%ByqUQzcqjABoBG##8{5Ye+tFA%d0PKm!H;KNCU`aL*&uim^EScTnfD0Z!#wM@{`&le z>n#!d3g&f!`)9KK1vi=7f|oPTyuE+D4a`l!6U?gwx0yEyUdeiP2<|J@dU~t-*Lx4k z=L(+9@@0Y-Gj9;Qnt7Yx&CGiQ?_{2}yuUuaSz6B$!Jl>PFL*A?w+LR!+!nl!dFG1# z^)@p%1@B;9CAjx$t!IErOfO+XSy;-XZv(KG5aZf=uxXJRS z;8n~^1aD?uCU__FD#0^%YJKViFJs;yc!GJ8;N8qy1ke45?J2nb_u5`Pf_FBs9ar|Z zXCw1W!AqHE3GQc}D|qLFx?EH6M&>1gmohIC+|Rs9@XiNx`E`OfGH(#PlzEfjiTiaq zErM4wZxcM9d57SQ_vvzM!AqI<2<~U@t<(9O^NmhRr!xi5k7}MJxQBVJ;ECUAc~kIe z<|UHftL4iC&u3mGxQBV2;E8*5ISqnWGj9?+pLvVm9_DR=Cw`~P?-0D2xh;4;^B%!H z%)M-H$Nq_WU4EwEe&$(%ciye#a|Lf?ZVK*UULttnE?rKU;ML5l1n-P#`8vTp%o_yv z->K!B1aD;d7QquN-zIn``&+l*-*)Nv<7NMH?CE#>Q1I?Y^ub@T;0fj>1MpJ8>sh`` z@N(w$f*)W#n*^`scC`yW>tL9{8ubrCb%PCCwQsTF2ReL zHwd23yixFM=FNipnYRqU6M}a?toyM|@OI|if}g?d^|F6Cb}Qv{w&3|JZwl_nmkFN# zkk+SM@NDMwg8P{_2<~IvD0t`Zb@@$#Cz!VjUc~y_g6H$N^YN!+hiNRICAcGRO3r!~ z3+}YHT<}tsuM)hNd9~n9d+P*u+S@GnT-Lu$a6iYfZowC_yqE7gc5vjg1n*`&vjy*T z>>zkM^Af=m%u5BYXI>_FIrDnKD_Q?0!SgxJw+ns;%iDrG@;=Vz*x^Bz&l22`FBiP{ z586Mg2H@3#`&qtDa1Zll!JAm0Ho;4Ie(V-J&hlQq@3hO2&lda@mNx}=#_;D<63+~AKc%9|+%b6^nCAcGBEcp2>UnaOCUoZF!M}NT``F6n5g10&TAh;vnF8G@)Zwv0oXLCJHdp+DQxdZTg!JYVK z3huD&kdRd|AOV)1b5`S1@B>bFYn`>b~*Cdf@gfCz_;D=XCb%QtEqD&gd!6$V9!HLRw%`*S{RMaA%LNZP`U~#JHw!-1(O+;!zFY8F zj{e-AKe4~y3myFhcgimlypdi|#J_UE>zP*xUd_B(@N(w$f|oLH5WJXqqu_q#O@e!v zw+a4-{o3C;1b>dXE%F zF)tJRm(1$~UvYsxA8ru5`dR%3d86Q^%$o!+X5K7#KJymAJ$#y7rdN#mEhUTs|EKluM^zEyk79`XLSEI3BLb)?T0ObH*z@%!JT%s z3GTG3UGP#ar$cb3U7dnE?Xm@T+SM(%(=N}${r#$(pTGD7&nnjK%@lk&%V!DxDDzyw zO)e*2@V~Nrwcyt2LoNnEM3JX6_e!0`qLa&tsk|_{Get1;2{hRWCWqHwfMo((P>$d@jqk2!0*& zgy3&Fb{2do%XbRCjJYlNK|CIN1YgPW-bee}`FG5Hg6DBLe!>61^4Wqv!8}*+1ze6P z__HiuB6ys6so;-sIgNssu-%#k-@xUx2%b9c68sgG?+|=D^G?B?b5Z|e{q1=X>ys_G zGr#8!z)iu+I6jmJ?yM_H2jJy`ce4J~f;;P+x&e5D;EPzFCc&NcRr3HmA$SFs(=K>w zT{i%?1;3fg=@HynFL@gK_lv`Qf>(1ne!-n}TGjwOSMWQy98+*--B>&TFBLq={Z%fw zv(Bs%{2P|96MPWIr3S&Bb#J5KBUrv!@S~U~1b5ckZGxY`@}58Tw|^mz3!mWQSUywm ziOjPEKaY8?;1@E_7yL@*#ey$jUMlz!=4FE4%)C+Xvz+)N_-|RhMexU%w+a3<^A5pR zG4B+7EAwu_-)HXmQ-Aw^!rUwP0p^*4AI$MKOYltQ*@9;?&lfz%yjbuHn3o7Xn|Ybw z70jyyzm0jd;14jb7yL=)je3Lf}hX4MDQz^mkBGOrfgVqP!! zz04a1;GKe>7u5UlZowbra(V=RmbvHg{&v2I%kc@mmE|)9|A4t)@E@3G3qClk*OR$| zAHh6d@Bs5-!B1gcBKRccrGigoUM~1m%&P>yo_V$4w==I7ypDN;;14lR2p;6P+AjE$ zEZ-scI_9?E?aX@wf0McAiT?dNs7Tx2C-_G!?-%?t=2?P&&pcP~5nR40xQ}_U;3qII z75q%*<$~ukuM&JJ^Mv4!^80n|f-h$I4#BILcM5(db6fDcnfC~OFLTdd`rH2r=3c>1 z%-7@BC-^fg?-%?Z%(DbfFwYiz3-esT|IOSK{B`EVg1^taMDP!pmkRzd^K!v$=2e3C zGOreV#D&^#>jXcTd4u4GGH(?8H0Di$=Q3{={A}h4!3&wU34RIlcEKI_4#8)!ye;@# z=G}rZrwcsBzuM>PX^LoL*W8NtE_sp9F z_whcxS@2$#w*?Pgto^oI@Wku-JiJHnX6D|%_V9Mnb!$k&b(gmM&=EIm$E)hf?ve# zY8KpSSBv2FTu!Ipj-IyQ*{n~u;6CO(f;)P8|JJ|Xr?Q?t!5uv_1d5h%SFKvRi^M1TT@J@bS)+u;9b6fBP^KQXC>Q~Y{o*u#L zS>E$he}5}y?iIY0xliz7=2?QbOww^LSMYq6&lfzKxhc4xd9mR6Bk9-6Jf0H4yPwwm zUMhGy^D@B`%*zFDW?m<_^Sq`(@J5zz6uh2!li=0Nn+5m%P3zwxcrnW-1kYyPCb*w@ zyWl?NozM2~_e4zB>uv7Ooph<-rHy(&RVKLqNzKaz&wpC;D#870G_MxC=Q+*m1o!__ z^LoiQYThV#=Q_=s1kc~1d9&b&4$a%xKIFxkD0lO;yEy%JmGiH|#gBI&K5Z92+r_(G ze3FYhzlTJ1PIU8UbidGl>33V4f3}P3H*@rzZWq@*t9g%$>k-5y{k^YzJ#sboy116m z+~?xXyDxMn)5Yf-L-Nh@>l!(8&^E>6G0==`g4@zD;%XSItT?&5VWeuRtH zyLhIHH@NsOT)ff6k8<%Q7k7T^lx{b>IR7N3%GKiHzjT$8aPcuN-sa+d7jJj*V_m$% z#gB9GP8Scjxb5O6xOlgV|H{RCT>L~A_waZmAJ1}euZxd$ai5F-+Ql zlO2f9EEhk;#j{=fR2R>6@zY#9-^H_C+;s6A7cX}4(_Os8#p$;roqwe+KF)#oEOYVk zE?(~9XS#Tmi=XA<)h?dv;&m>b=i>D){(mms;Ns`Fc%zF?aPcM=|BZ_`yEy%3rSq@F z#q%AA&xDHyUHpHS|FgjVEbu=I{Lcdav%vo>@KXzXWBhWT8TrC%Mh9=XXo$zGO;il( zZ8swuy&IHp@A$tJ4e{*mJ>e;Q7-KvnUq*L!CqL}%?X6d7+7RtdzL84PMre1kHI=3f z(C*|vQfb=w>`wkMm8Q+s?&R-MY1#noPA*TSX;HX4d3`EP8=l?CS*bK_bap2%PNivs zvpX3~rDlr@iFBn%FBIvyB7LPuPZjARkuDVJ2_ijSq)!p)6GZwL zksdA5BSm_!NFSIi`d_5K6zNZ#v>DAffu>7icuVzTy}cV~z7AdyyW8)8R%kaEJtB#z6{T{-!8J%z#EN0)Pu1C)t zJJ@4J$2Y(TRBhdgG*8glT$?azKZe3)bo3o05F7s(K1kr2K7kEdV6-aXoIqhtB4-PV zDnwDXCz9@zGXqN)GdAJ1O&K10=zb^=8~+QJPUmTzZl_$IBg~?V*ytx9oU;e!v{%Do ztWXct7n@K^1ts>Wg2uWEI)Kb*+?iC+AJz4gfX|HH8t?{NXqAI{Z{9)X8X2Y%zJisw zV0tcxf=?!VjV?IbRq*4w;QyY7f=#7i&bD=AQR=~WUQFpXks2DE67Zs?#@`H5x67)C zjs7F@g1$$NflOBujg9;R78ho;B9IA&MxTtehrL>5_*bABJ({zPginC4n9)&zu=Ob= z4?>dlJ^~ent*^+TJh2oVqg!*;%V^E-zwhl0TMGhNk#7kI*ONA>`6%#;8n>2LkFQwd3(4(T=-s zqT2VuE3%SzJbkbdQziV8@nQ|2z#?X?es zL(teAj!%ji_dbSL7Ck3mzcK?c47xnmLN|8VuVC=d2+g#!)lk4#weL8S%D*+>v;Xtn zAgbBkh+?hv+-j%C4Z!5(*mkHpzjt(ieZPZyBqum`&T_TueY$hJbLYRVJFRqQDDD_z z@@aIbLhqy?lu#9hqZl^fCL*4*L6}{_`bmUTxEdxE3H(EeJ*J*579+c{f4VOC(xaRs0SVZc^mSM5r)yN z>nMQ6CaglW(8T`BcW{9kRmuieDLbgUPedsYU5O&>+aQ-bP3L_Mrmz-F%aHZPRi?GmjC|Z(JS7|({J@$F8XRNP$Akv7 zpm+3={2`ui>!I0AL5h=um(WLEPsM0#wJ*dy+G-E&?KH;FnD%VoPsoRq{P>CVG4@B( z>NZ=yI@fINNjK9rnQ#19F$x8o!UcGHJLjo&yOW>vtDZ0tc|DaUO*JDEhCvek`ANkH zjOfFWu!nxz+iTB(ikk+1f^^!I$eXI4@+WV^P1c9fQ;V!t(>f5e+SG72tv6_ljDGng z*zjZ+2i|{WGJOx_@dPg~vR-#BFHDToP;{Etv@jy93IuIyO2CgncXGc)M=r#25}|0& z*LA3B43`+#ptAO(YtZ{2@D#gYp9HMl(2_=)7y)oe-7rX+#<_1qXkeBGhVhC z#h9(i>Miz{OgC%aH)`l_?3l4hy*ckIU)@{~z??zGEeLoKoI_YBSsS{3q4kd}2zb+| zFs}*4jGB`uGwQ)anz2=9%LverqrV_!MkirbAJv8ySG*j20X^oK7#s147Hc=R+cgQJ zrWMHoXgSKXIwr+{I6A_o%!Yp2o-{YN!by4y zja6Ihwy)s>4WYEnkpn$O?P6dwdsNu^CZ{(TE67NLeMTj_FigomB44BhBR^m=JPL9u z)F^xDMkkL3RB5G2*xG+ltU$FY(wkOM5ypZtHu^ohB7op>$!^teCsV5iXptGM36N*a zG0)KJ+sYDi`9^Zd8CM3c2woYyDmZh49zWK*CfeBg;X$$M)6~fXiew$A&i8dd`v5J~ zbaonWv+P8&4N0YJW7OUS2ZMb`F~>d| zXba#E$KbbW=qLxEb(aqd5Vp@=3*Jk*@s z9!aE`4Vwx^`G;*P$neAa(~GR`0_(%D^*L64ddwwfkX4Jidwb{2JJlFdLu0`+Pn|cq z!i!I}z_okv0#L(yE6UC25VADdK3BK>s=V>vpFPB5eRu1W;PUU)TIqrUt1V=G8nWID zT3h#a^tBOd$zs*MoJ8GE*Jh>Twxb{v-W8B%`JP&V%)1k@emAv2)HwoC`)iF^pOZUQtxL zr=lcGOD^=%wa|-$Q%*v;YmxQ6eFC&JqZt7N3m-H@6vQk_yP8ytCk=y}Ci`Ig9YJI4 z5Y z+*!SE<{CP1G$ySNMK-0OsEKt2C;P*B|I)+0_ItHV>VA<-S!DefvNksv6}irO!TJj2 zoPiK^8!E$wW$d0%WOJH5jv9=ZyeYV6vr+l3sl{+NjJA`VCidyZcCtNCQ5gx=fsvGf z$Y6a&N;Y8`WVb-h8IiO;pwWhSGKBnajP}FKqS`GLhvkj8a))?s9iIFYs{~%BxJI*D zm(qFxZiO*zy{5cQ#Y$yE3Yg!jewd2o2OU;q!36!rLM8w$My?3>!f+y*u5Nw-M#n<^ z^se4sbUhkUfG)H?FVK6X3lLVqs_U&CIf*_$SM?NGZ=i(VpalDy&yhWLQKrm49QkQv zQO&85Re2~z6)EQ$Rrc?ofQnaSAB16LpHvtgzvwK4VXw1pOMav0N3v(X^O+``-cZy0 zVFUtizs5JUpA!?(trzoZ<9 z)!2&xY*phwWW7y85i199?D5Ixm@Ni?69MVaepOA9xSze;B^z4k}=i?GJ3nm{A;z$Rm6 zu!Pn?%b=}kT|v=ef7dX~x5lb;OrCRS?S=XKoMDw;g~sk}=|!+mT}xvjOszp{L(6-K zV-XQHCih@FYVSZFLl>>o#7#BlkeCPCTGEy^LZl076K@Y_Y z+%(3f8)LD6i?x_2AD4doFWXMLG+mu2ybDRPXdQh*cPxPs?v#y5D{FJ~3=H92@y&JOk%$gSX=&C$Wxh+9fttKIxlk0?(4V)2Bsx(u|sWaT)0uWYqi( z7o>m6)X4o1a&voNrcCo}w4}0*8ib`TH7Hu`M_HtpmmH{eG;OLV=)=YOynHddocz({ z<+7$j`fBQW9Q_lHUf}E3@7N)?;jkcCfpIj@ee4*MQ)v3X5H0PS{Z+h}G8Lh~uKf%P zF*uCJ+EozsW7&I?!Bu2^8t%|E z=f^RDQP_$(94A%qa5IMGwwnK7=9B3n-#&n$LH53%>cUn$)2#inGCO&@Dv#EW(WwZ( zm6`VAO0Xg?dba(0wB3v@%xZZ7t$=(*Ai69gI(0;}(yPj|(&?=8rk9n>IxSQAA6>e& z3w4jMSD`fYJGO-3KnePHggX7LJQB}+%XH^%X!$#GcD<%Q-my1+O5LURzc@R#wg#tQ z(S*4CowAwRU??!PAS<9iU|$1`bG8Lxmln2I+_4zUMVzeRGYZI9naXxh^Jrx&G|;Ho zL*}7HDA^E^UY&Ziq8rF|qtI#8I(RNb_d~SL9$!L6+ry}%r2-X_5o|$B@vNc2qm)OO z%bz&30=B&)I&G=Q?Q=o0X;v^{WTD_ z@1^@M)l<5K(h*8OTOWLZ`YlMoX(atEl$lic97p z;UAuhC)HTBvFjQsB2PL3!w(7ip(q zPeRaxZ#~xapy~%~A!08C8qpr)bBu`m$htWl`Ff+vJofEu%asr_R%`J!G;-FF!E7Hi z*Unv4Mm=@3bZq<4ovPCFQ?0gN_*ivM&5LlS;EUu*>WDBEAIX5}Fd+5i4acDO0zoSy zko-h>AL3E)Me)s1ZYk3Y<~>@m_0vP9k|3 zm|jm%Jnk?5e{T6#y-NO9{p8K~`{P!8v{Q4t3gyHSZsli|j z->eOG;=|tFK7DI@s|xK?(C(m>s7+KIRA41$Y`}Q5r{NSAJ)LcLcB18&l>HSaM|#RC zPK@**^pG>O{0oMgQD77%kZD7(Wi66jFX?+-tAj1glzuj4&;IK{*fBcB)nrW4KsgDV zP}R|y(DMDXk}~clO5Tb64vy|#N2JDh=hemDAMo(NoW0*Z02Qrwaq1nrB@OGI7WlZw z+}?Tq(1MM=0&T|miS0#K`^;ARSJtNa37b}F);K)4*)w+i{PmQ?!LeF6;QSjk8U=V_ zmb19Al>-i^}))y$mHO8>f#@>a_ z)mOmJy8hkbX~4%uZL$~bQ=q?VN1@LLv_GML&bOaI)v|x$*o>fm#@qS0srx5~`Ujna z{;8(^c@7L1k)+(~P+K-Y8JNq_6}hX@|M9H9s1ja2a2b~irsV4i`+Mh%%qogbSm z)fcCE=p_+aGZ=^9m}0V*&!MP1r@yfvp^Z;Y@1^kbOnW)nYDTZb!7P$hq`c$3AS+uJwv&lx;%u9K$#hRp7Pr7%t=E4 ztvm_CF0;VucDX}6HNN(UUOf$GkD7Zo9YItl}UHEQKL$YF2#D{bNdP0#-X=2w0Uwl%7TSf zk{3{%O)Znu=`79dnRz86Za>q+T<`T%Oyvy=7A7#OX?c_XMquchzsSNNYe@2WQ1s8b z1d3H!*{%OUo#f~K#otXzqF{5U-^7Bu^u?hK4VaE!6{`jACPy7HLkz*eKj*ujt~EqJ^bcPF_1Agr#O~u*Fa1Snp#0zb+e>z4cz~N#dhX z1*FuX1**P-vQXr6^a15yPI_n5z7SPX)Aqcd?wN)sfE{M+PBm!y{0|Q)alE|=&wKOQ zD!;}F(@~^6t=Dvu?$ITe;KSabc5>Q`eXETVemV>Gbt1Z;IC&o}xlVrl=)pYS+@BAW(&eHP*-Uy!tSx91p>WPH!Bg6?y%yPH$YSw4vVk%;}9&k%{by{AYZw z%^AXz5^LABei&&Nvc@k&k+4)96@$fq$Nn|;mT2}x#MLVx3vmn5@1-iTv2LXzo8L?K z(6Kqx>}&l{^nNu({0(+-2Z#Be^G8~w|HL0N0do?9hFM?v2BH14^2ctC$kg3lfCnCqS`SFP^f4rMYhd=u59C)+#$A<%*)Zekug}Q3T zC1>vcd6y(V{HaS`)ZZlwP!@_DLmw`eT#H^Km;CcCmrK%?QIBu)C;m9KzdsJr#kM^O zf4m6$4RyAO?0r2#{z%q#O~XIukAHgmXZ#V5xzIM3OV$KB08(E0%vb1>t6W~W2YR5D zdHB$MvKC8!-6!Ogs!uwQiM?{ZP4go=)8m9C@1NJkxdd`&?u8*19Cu_d9Gn_eH8t|IG+FQV1TPxrzm^a`1saj=6Z zloq3z_QfQX3Z+|6(6zq!>!{HQrEfl=T{p|V0UaMkD5G_NR^;yxkG~0F=ZA{-U!CMWN;@)(~%%HNYy{1vnZpI!Cw5x(XP!F)|o+F?LHujx>$BU;c%5x75*DO`r|c(n!IiIww$S{{uTJGT)Zr)WFZ|W7oR7TzSEd zxYajUlown;QWU~>+2x1hGDZuq&+KvSxQ26ZI1fNWKeURUr8SKI*%>%9;CmQ2xx`gC ze-yVMJsi?{gdWLy&0@XcI8@RDh#Jsmw}W9fYNNK>2K)MLcs^oACzp~Ta00EimU)xQ zjhY7`75`qn>N)x}REL9a_&C)%iMpjpZG;L-&FIu}Gg_y&q($YXRj)3i_fxb&fe79B z7-m{HA%e73rvYWE%_kAOZ80XYEHmx4BhB=QndV6o{iaoG;!aNDN?sqifbt(a)`$&m zfll%7pr29;zWCceL9Iiemde-{9p}~SwbW}tyhDQ{)1X?{=@T|`ta8!R z7HF_bJ;|b#YF59%Nv**c;4LH?q&PwXeC2-J#orYf=)rQ`ICO8=Xx2hvABR+;U%CNC`TK(RU?K3>qZABq1LJ8q#q@@_3an0>ghcrJk#2QEmPhOqsBs{>4z#mNLCUf8+1K^ zt*Xz1#lHHkkV@Q##1slo-@K;wN9w#`N^b?Wm-L!L$ZEs+m}%`ctsh^avwHjN1HHY| zr|Cy11$x&P96+94Te64$j6CMYcW8brvR>x5&eaITZrM+cj|Ya22TIXw8VcBn@1mn; zdfb`Y&;Rw}&VKJldfTwqJ`N4QUOSv-tIay>ix;D4cgH?{1C9PzP2h286<>h==mT1Q zqdc43zn&C+59OHAae?z=x1NEQmOi(KzTVsW62%*P#{n$ktxal_oerXpsL@^L_0oIR zFT?3iqs}MIQgP0xJ(OzJYbJSM45!1eCO`M1o%9O*eW*zJ#v5qIdTN1bucV<3nQU@V zyalq${shB}--;fVo{k5)*m3=Xa?;?Uk&=s773kq&J}oB7@pKer;=vm>$QdwYXQb1h zqBHBsx{(b&`*D;)FL`mHwW@r)2o3+oC4H`d#2O#!V3Di)R9J~i^(Zo&_mQzOPOhKe z@eF?-bx^Qw)DZ3On{NCH?&^cwl3IG)m`^3=!mN0g1_r+Ehdu+pfnrhy{sbb*z((yK z;H_i_lPsdVW9-{zIt*x+(xB;QrgdaEJ)%Ftr7{!FlF)=sylARTqXN#Ft*`2TFk1oM zCHI+o@j}m5oEB%8v5b4n*3LmV9#-)KK>^1x)@Elty$f$?jI!sDm0SU&0M&5-nXi<< z_aPv%28#ich0ew{4DFje{B zJ6LroAFn+VrsnQ4R&0Yr(ge}#rf5dM5i3T}Vx^1~^j=@`Y7k}JWGSxj#Dika&L7kz zMVxnVX)k|;=6f6~oq@9rb?WAw2Y3b zN@pYAuFFKbuxfaV%F%~AAER(O*9n=?!@`!|w94?5KA+rIP4ih!Jf`Rty~KwYUHPqP z1${XQwVsEO$X3)>=`%2iBi^-mmgA)P!+ys%yxw;ned35_aw#<>)}oeQuVd+HMsF#_ zv@rvx)+ohXzL{2G$=Xfnec!J$qqmph2Ay{#AI2WoRR!m`;d2NpsuAognFrBrx}e%`ukDvD{zor9wD#N2)b@^uX zJsoQ0EfjQOYnA0+e^y;9dw;Y=U8@c15uJ2>i`V{O996cKelf~E6yME(dCD+3*nioi zOjS-31qK9O)w{P!U2m&6+DzN0^yxA6Ja6W`Q~5PAlCZr{Wqhh$34d8}sEX&&g+6-< z-N4gntfAI6ljI~_MS`x+(%0>DeG7)78N0Uut5+E}&~6@aeFmkiOCuKDSfaUM24-NAgc zSzVDFD!UYw#mjX~XE-&PRv}KZu1x;@P3)=ql!Kl0^AhB{tO5CcK}+G-==~31e|4GK zoum#iafDfiZU{%8q-w($g8dd3YWIxz1MXP-FCOidz%NjMW52dr} zmo*<{ulo*tO7p6^`5A6T3p430oV#De;Kug&z#dwptfV7Gq;}yQVWfI63Xy8vrBWWc zN7HyPy82ey^F$K4RHnCfk5P-4^wi*rUxStfdsq7)Toik(gg$T(7aQ$EQ+Z6%5ol#Ta<_EUAV@r$a$Lb1m(LBiIKYqNtb`7jL~L}8A^ zmSptRPHDm32dN3c>A@Mb2~}Q@UWvs@!>FY{^cIReNUEbh!d6E}&qLun_!B*5xLZ|# zBeHBtt;|9}bn#d&Up#2y!WfJD#vw-;hg|AYuf`Z-uLu+yW2dNR7k85^o?EEDf~4l7 zFy7nM^I1{e*W|Z&bJbB_ogI|XphFv8gn`u8akve5kqo-i8w$V2a8QPiR(b6?k1Fqb z1k&-B)P`zT2;X|ZEA;oJ_Mi4?*b-4qa9Y^90J7I+D_g}|wd1XTu<8vvK;C1$8(*)> zg80mLRq&cgBIs4Tq?!>Rd)wdRpdh{hayWmc;Sd{rwj+aVN0a_^oR8+%uR(O08M`$9 zDkpx6xD|{RW)wz?yb=4LU~4ix(s`hep5_^~x1zD+wPD(AzC?%FA?ydT@To2`9pWd| zj8*w3lVDb)bI>_y=8;>lN}}gqkq_}@hE_aY!NV7_gPH_}{V~IH8I-=`UT*v4XvD?w zQz+Q{*iLZ(4ssi&m(wI_g0!thsXh!zboX5|;X+td z7`1;@{XP|ytY|@F)l^i7EO-kJ8(kbUVFZ}bH3{6qmZ7&jgq=dQO5j_GJM3R~(YHyJ z2TdlU>O&1IlId7wWZ%u*XlO7xRh8dGB6v{1KlOq z))Y`b@On<~SzX(fizqBD-$+psZ^if9s^?Q=_M?O2m!o$gJ?TcxaO$Sm=z5f|p2DKj z5j01ll3?6}HDA{ws-E~CA?E}rrP!KBm1378qx}Kx;Wz?OG)caSw`5d43V^6{|2?R4 zt*+_>S5@}6PHU2~SPScQG?ky3yrO@)>kp~*6zjd5^nMb3lAHwfXg)^}#-rX_1I4_@`M^&5 zn)W!#kuHSI>1J8#=EvQsn>o0tzfib%?;wm#yqFEI4(T^ZKR{rIYtaj!uu?F(ER&oD z-wJ@5Mh*3rk}ixEVhW(WW?Beej;a`rua(hpMYlQj4U7*pqVZzZ4WlCVAbLS-CAqel zhPS6N+QPAOjw&S2!70mc$RJsvSjI2uA~X4&>actjTOw7Xh8Q*fB6VYf|Ey;>p82NY zz_@Sbdk|-eNYTufOvBqUun*fUgg%ZplHG=@od>k1BO$VzX}w1WQ(5->-8cY%37`eN zGeCHgJq0lNE39pJ-KKmV4)j?)3j7deNUotitH+A694W^mA+ZP&YARbBpfQRW<1Tn+ z!K*5AmFh15_tw*#jibVJHThK@jT6LbNUzPNEO>_mE!PhgjlvF^fBh65bv(Zmb(~0A z)KX`}Mqh>E^&H`W_fvV_}2T;MqP$^$AYq<6b- z?V%T$(L<=K4f*0RYH=IP!FK&8L5i%&fA+zz31SKBNj|C;g@ea@rTT^YEay{qpDo4l zy3=Pxc!P$VB7_+0Q=Va3U;m7Abf9n5G=sH)N4+$eoQ_^#ot9AbtEu`iRK2xBO^bBX zJ`?LL6{~6!)`rTkx`Ftp1KE-8n?}vfee{YCeL<(0wj*uixUtbaclO04d-K0ZD zII9+|CDB%hc5PR)Vr=jU=$7~xSg0UsVzwE*+EoAo+c@km5!mj=X0{a-a;8n#iNsIT znMQSOfe!m)Ah%JYc0kOIttCqh{)Fg>M7MytRr}jqg6Br=)hWgqP8Fj= zilYAtl%tR$92=>XVzgeJqeUBN6NA@KjG9_pgrW}zXg3l0aj;P{4j}R)hUIW|agb5- zkh;K41fnH!Gg<5Ubi8Um!{M*KKTJoKLYYKYQ`=`=uNHG&VFeE8yO zjjNVIgB_oq*P8H#(%ymnZj5Gl<^}P45+$nmqSDav)<)E5zp@o3vFz|zY;X{1?!s>` zc(7=UT{MU?Bg>Fb-d1D9b-W0ZQQ%&5JAGDkLM^_$Q?6 z2)-aXw$04zFjl-mL*IIje$nA|`;)jD5t+&3Q~`*G*4xQj5W?WjBj9rJjbzH$;0^F9 z7-#x#UEVns#~lb~Ba#!5_op3#08D|-yGHlMkM{iIs5dIFboIn4l&%-0)5&eo`JTR> z_|p1mPtcy*&PR+>zbb|J+oD`M0gd%M=ji>c*1HS6sirc-&o_XaDIZN5id$&XO4MQ> zycwHvn*EbEpd|ZlY|vfKPWw&0UrW7T62b!!e7y|2cIO=vliob0NhkV3z=oFUd%Wt2 zNWc9W9U@>@F2gjrrW)6w=sAH%&k(%@FbdQ`sy{>%rJAtpaS+5au)2c47`(qf2=e0s z`ll#vPLeq*euKLz_B@2Ubf`-;q*g~L2qT7E6)U7B-09~{1q>#qSHKGK|_O zKs2X&%^aK>ER0 zsT-9}C$piv&6OXUd5#WuKnFAOG9FMciBwQ6G%fAN(I++G8`g+^9DtgJLu@>>!5uU0 zZF>*jY@wSpA^%8O@C-^d;!mKAzGQT_LZ8{ke2HnB-t0{6XQ<26Du{}XjmxsBKVXWQ zE1*&Ga){cwtNP^0pKy+})lB>P(s16(H{#rFyK}CQV~4B_p}p^ihT`iXVe7q6>wbKX z{_}H{dA3v>PjbepaYOL9Y*bpou^$AF-BvL4?fklN>hL<0*IN0ZG79#Yp*(x((>RLc z^EtJU&4kCtuf^0h74Bbm2S$N)KrO*9wGY||J4BZG@pP(}d?s33N*}RfW|0`Z+L(L_ zK&=batmkxs^I%Y`bYGs$cWOV@{M1D?tWlg^yu(Jl6Nds(WZV71=qcdLOoF z+i1~IY({qWkbdD|Bjak8u->z8P+Oxygn3o&G#uIF8mrV^>?*y-i`G*4s*IgI;jsx! z1cOF~@jxQ|d74~$r}|Ond3DrC#Nl1|P6S1@2wJanvge@1g?K7)_etm`euWQbXzHk; z5Wn$&EH6-CD2A=Bs8!!oj168%JBr^@8K}Zzx39+wG{`&MIg-V=ddZ7BUB{-@*LYo2 z&3Uo#>AlryX+~`n_anRTP5Y^yoGtmrs=a+iG45|Q)3%s-uidz%W?SVFGjEeo^9UK3 zwkmjQG5#p3MzdzFR1xgu8iY>FP#$|S6zOY2H4rzOGTopv{Ti9H^pP%UoNpF-^d@&u z#e*$WTGz_>BBzO}X4LpAY!6_FOHm`tf<=Y>CiWc3jqvXHLsIznTKHE=xEeOJpCsW2 zA?&>G9GzTh;ut#GqK^0))N6HW?6po1MQ^gY$&y4w@tI&#K2+rKjRx z{li2Dqoqe{i@`<^2^ub3PdPqADDHl171RqQOhVQ0^>JuCHT_nt4k9 zD@zNa&lJ-oy^(z_Jhgf)nJcYg7{1eVxKTsfItSrZY#YZhk)BaTje#ykQhg2bei~kN zctc?sETR(8qReRFs68ubXb-|ygRt|co0wL2K4fZh!9uNHcnj+MoXW2&PeZ6FN2sAQ zYRu2aA%iPWyam63`9E8Z`FYVxWaVWhgcCUNL7U1Ejf|Rqszh})^;GnJvOzc+Gx4GB zdT_2up(R?95kHv@39Mb0z@ip5H7NKl6s#8Lb~fA+`6zo3r~M&($3CBCxOpf&vL9>E z+i@qdA8n#P?uN?Ef@n4ENefAbtEoCDl=FTvjui&);7HHmM(tKOJQ_`E8LKkM z8mr-)T16H4&bdb$$peMh@;3K>df?hJxbqAY9V#a zlXN7+V#2s%FZoOKMamV5Y{a+EZp^@`{0RFm{~$XmL7eZXQc0f^(XR+ZrFat|dQTI2 zqpm!I(k#NPcra=%jZ~8W;+D!iufQrlXj8ry*;U$DU7R-0DjsUADo(E}9!?qXay;pw zp8f3Vt?#CefKRdua?CMm9>)d?-x4TQM_sogk-UdCzRvuL0|LC&e%DCVu)^{+6kh4| zqHGkOh2qUvRk3~J$Fu~(U1*34H3O&{S2;H*u;B)|qq z-UdJa%Q~HL+Ev)tWIhYK8bF8nkiR?>IHxuS|~J54rR(n48iF59A7L z{P?eEG^>5tI_x`DLwK_1^W20oXr!|Tjq&026%}@P&4HSzNUVv58LQPU!dRUsHdaj> zME^;HZjUU}zx;5l(hJo_HsYWa51v%uh@XVo(Nh%GRPS)rXw4C5O`ir%?Xl5eD$w2y z3!@nOAv`jfc9r_lW##qp@hHu)i&}LJ)!m$lJoaO2$TEo0sdc(hTSwN8Y^>`4HG-7? zTd(ik5&3=)wrf~J7QT+-uD$I#x+WjN*1VopH91r#)Mq2!R;?WCFSnw`WoUEPomkhz zF5MT|c>w!sgen!%4#$Q1Wg>E;OmZVLYG&e$Ef!2O_u>Jb8rLCfYiR6S;k+c`9r_&K z(azb{b%FB$vX++ zFdv2klh7yGH)Y`22kjrO9f=;yqe0lFI(%w5eL={Kp6@rKczF}2GLasyQ8P)o!QiFn z%lK1N9MbH(Y6F5Y|5JrRW@8hHjY<5d{)2rsDu76wMCw<=x(~zTypKWs_hZ$cS_5g% zijBULgwKFdJVBLAPc40}Lo<=>6SN|JIh-*`FZ|KIGx#Fu#otmYfSP_J^{XsLHql9| ze(UUf7$dCbMs*Y0X#4vo>Ha~q_osCe-a9~7@Y-OXeF1V8)-A%fH}(4RUfL2AS-0V< zR_E!kgkM#w8IN(Mp0nupVetGK@56+x>ob$r;urI{y}EtYE@KtCl*iZLw_sRwFuHaa zB8}RN#p!Q?K|*^kzHaNoqNg0j(172pjg6jjBgOe)u&Np`G@*0sxnIS;*x=i+J&w~~ z3_};332DsUnJU=O+pC#HXKa8RPBKRTj( zAE#eCg)`Ej{w{PX^t=nt@wBDV9-&}tkA-Jp`HSyg8a2mZJW>CnE%B>V|D!DG|4sR1 zMl~m3NNvJj$L16~zwG~IC7ASLdPM(NZ|r?HvTqQ=5|V{)=y{CCQ}QXqOkO`v+?3(P z4~%}9jN^(A^Ev3c^z75&Z@%UbaM+-u*;r+ zP$$|0Wuvfu{8uP2c^Gn0F98~~<)Qhi%#)ARRZgnD*yzrR)RueJb2M)Sr>kdJ$dyk; z&7q>`2TG_Ybcqi=ilT7)YV2RjzC9P^t;6D3w-?VpQC>mJ`~h>L-pCK9QfHPV=OB98 zcl{ZY*I!fOq!LPc2Q7txr)pL1gWTKLPb5!A4pfB)(2&^+Ww4i{ANhsouOX^xw4a6~ zeHCQRpVae+rn^F&PUnyW_$r2!_td29KDIB;w6^6)~@(0 z%E1l&mCkW6<@kg&=*!XfJlKpH(dAbl2YwOd^yqR@EN9!^f6xI0jzKF*)KMeG1y)*b z*p=TKtF}ca`*6pa?8{q!>(Jy6*mP3;)K2tA1-8PD#(%^q0yMsB3F;pWjq&IK8u0f9 zRJmRMbe|Xgh5RcEokcb*K`zIJ^!09^y-ja+N~>Gc8G=!JEOZRVPPiJ?blu|Y-*`7_ zMlbc+rSJiqi@;4U%`CzX9+30vjY&MDeFAHGwLV-m$*01orTPP7suYh)=m-d!ymmb{ zI3w((WI-&y|BYvW)2Cr#sr?$=rbMF+N|e5fT78S}a5H*_QCoqyQ~jG!M(uUDpnPZG zVJ3R^3fxscVaxF+vdrrS1y!^s}G;JKNW%&jwRpYK76^7AL22#zy~GuC`7WQaHH{*>r2MJ*lU_#qG9h@DvK_ zK0|l4W@$+}ltz4_0*k0X*q;W}It)J8=`Sc3>zNVuP3S0WI!2(kwKgiAtJb9_$HN@1 zM;`oqPYwIeP)__FI8cyYm$@9p(NCRyr&{cM8;C~JmS>=JWLXwYH4erg!X(=aMOuo2 zxIXFrMzYV?_HdqUtaui|3Jq`$9F3auU_HmcM$I4TcI3qdXD&g85B;X}B6@$kf zfpA`%v9b>LLiE0~;zsQ}s&})JrOe8+VuQz{0m|Ok2E67B1T^K&#W3|@q;<5G$_>td z)sBVmjQHCSBUK|ibbUtcYg9D+7DMun-Bov-=QL?l18f3>8%ZxC+g<}uqwz^E2VB^*1uEO+m1Ly zQ`do1GnC8yjv`xZ^x8!zmdymQ=yOdX^bLB~NlewuFTgUF(^4#&nHO(F15(lz>sasbS#^x$@78!Ae6 zU|6N*6KI`XM27{>lOT0XXzUI=WT5_6okY*6=`cU~TRQl|(`VIJ9NQ=lc9v=*I@x75 zG+_ue;V#-XS-YrbL%0oDM02 zbkzvcQXk>GE+e9T4h;tV4c@<_HTRhm^mMo-m3UB~xp%atzGmtp%jx5VYw||Be3aa~n_7xA1 z4?}P5d3qUwdiGoggDgXx$y-%fHIN|F7GWIK(X0^t9gU`fyjP6K14za)4$WJCofV-NQ6C?(K=P7z2AS&NU`_ca8!!Uym zX2~$^jq7PtAWo3)sNFKY(8Kl{i5l^JyceotsD8exz5s=x7s*{Nr9Q($s>_|Ie=k%* zzs5%Y{aUqQ4Iy zneh<_C(lEdB6otoUkQxYU=>;)e*vKD+4u;TA=NaJu1$G_Rts)qH&EdZqHwHZ)I0UD zk@PG}JygdJ$As}TCVIOWG*+tze)C%GA(74@(TwHvR<_Sr_0pX%YV@3VUXN)^-fZS= zxZ#kXbDUiJ7c#iD0nVSADb{;>33vqZ z+ReY$?ox&qi!k-H(rik;5DRNXA**Iux_7p|w+{wJ%`oSf`OZr9Yc!kZ zVbXzmlHRyI5jh}A4;sHI;|GmDVw|XswHN#a!%MyFFg?4PSqjz^g zjsEARc)+?7Z>_8!5z2eRSg{=2CNp|>8^q9w>F7jbRWQw1b^V~$PG9S%-l5&NP9NH> z=c@)YtsN?rLM78$N!tpXr>4b^$5xeoM)ytZX~=i!N2wj-*Sv(H_49)m)q+jBQL~-2 zS{=-YKKC?6FP%~0e3qVUuECAyJ@hoMAa;H)hB3Z~1`Vt8@UrGmQkCLWZ1BCbYo(!f zN&GC-4VAWDX)_EJi=S3yxLAue8p;%hhZfJ(M-M7(sE1u#_D6f#!2tIylDqj9%igM=2Ikc zr{R3(eKZh$j!-cb`ncxJOZ0ZU7i$;$j>jo3Jg+uySl|`K=6$Os7kaZT9Ia2Fj3P4T z9$cViGHx*Xi#!}aK2P>DR#hE@Coe;a(%v>!l?-j&=?%7i<_ive2hiL45nl}}n!O9R zhHeKPK6JY|`~6U?;26A*yAf|J(PAq$X@m*e(LqgAHQ&tJY^?kcs~I}Z&?jEoaQu{$ zxU>kriy9lenA{W-I`zs~Xb1Wt82N07y&Bs{KHyNg;u$=C?fusyaF9E~p8f#dx$z6l=sitRmHnHug1&4thyx=5-q@zo9;}Ub83MPd%^8)HNVTl+t?{(Pr{u`wE(5 zfG{a)Z*L(?UqK#&FA~xB>-xS&w2!_=M50Q@KK35YiogI*!#qkYh#ySD3T2SlpPLQq zZ?2{y=^tG50OD7#8d!D^URg5zCxco0gL))Bf~GV00L2L9bNL>4nzeiEyTR={3x*<` z(%*HcJ0kfJdQaywR!>XApdV_~{(`3HRl)S!;BcdsCU4Y4V>W?_&Wx;4IvKSzrzW4l zf6#-^Q4dmG)Eb->Q>cxN{_1MKZaDrl354d1=U3*lA>>vhK@ z`NNJjPKL;aO|aD|@$!|~#tjhG%5mKyhOps}FNW$9=#?cez7sXYT$4Oz9i7Z5Cw`D0F-W7r3%fs>5jiY5ZYbL4vm`EnAM#S4%Xjo*k|um!gtxr5X7 zZ}!bdUVwbC@a$9_%EFWN4*gE5?J%mX`fga5&J~@>cq`0WjG7kG9-3wyN5c}zv*S^$ z#Z|WiOOhw5E{>=5ui{^n5#yi4n<3ufLAXoqN9%)A5H#bPPyx#SFIsYG*CV)^fei63 zP_=mbx|F9VRBo43ex>4CL=1z3VKp$ucy#e-$MMaGYY8Au_5zs6ovI`qU1;u+>l~S*$ ziQtvMCM4^+iWe&NU#q=XZL1Y+xh!4?pak!T^TK@Vq`*9v165n>xbTDWtQQ{k3 zd|m$c@2p&cvefSU-%yXX)LZSLhTEu`#yAW{gTXj3SO*5{!C*D7V4xo`SPuqz1cTGT zU_BUo3U*q-lrO*b5KbAJ@hpN+=SkNc9ZB44$Z%!=oXoFm@N&a5w1fnO ztc>(9eEC*Sf^f>o5qaa|Nc=@)uO)W%SDKW(_Z?+P{21Sk*Un#f9@-M$-mkXc{FO+> zb-YK}Gv@v-K{<6n3@*9RgK(^Lec}RNZomz*SPi2>l&~?DFV$|_|1ln%aGiWXXi=Z~ z?VRa}Q`C}r6kgLmV`3=an|0A`2`^9xlHdfLHP`HgoO6|);L`4Is$a|O)byOBT z$QyyKCOgV$bWd`g+F^Pv1(4}2tu2dGicu-mZ~ggXpGtNcb?2`H&nRTk%Bv4xWNC8? z<|P1HChr76*Ej2+tpnUE2diIbf*}5hitS^7O?DzTYo9ayS~m?UmZIqb@smX9P{U?W z4JZDU_=ZX&6axyUQ8J~CRNYbmyl3z8#Z_n#78ld$_va&6zhr`MirRO&@X-wA-68O- z9onrtI7uo~mKG%{vKi&xc3mo)Yx2Dh-?fFSIcn4$lfEEmnKcx=Rxurb(BICZc}G*Y z?^KYp-eK(saQa;36phJrJ7R!L*C|sqGzl`9p5&J2ZHof^OY~Vfh>X_YjC`DO%!ht_ zH`!iJ1C{iHjzIfRbaTds@`yW(CxH=y?^`O z6~i^8#*)qT^oZR%Aiu8aWDn|o2O*yRmnfy)0t=`#fx5l!%pKYMeF&2#t}DRkkde>@3kJi+(Gi6q|QmaI~Icj4x@g2d%tl~gp>=Hn`1?mD;~;sbVV zsqbRs4NR)q{~IXmRr-Tg(;39NSszW^%pETrQa~*~;shk)wZ9gTnQ_4Rx95mkZEs0^ z{~0Z!b=xu684J+G6zmnSG@pD9oiAcK+n@O>GRccfvUBB<=?5AWjhAEF(JAWmt0EI1 zuCpk<-f`7H>c)m~D;4}+28h!E);cSeymbxGqIl!&q-Aci59$_CQ{Pl=_*3cRJg{UhOe4!#5Rw{L(K*W&V}9l$5`SqjiKBfot|P9@4mNe45{#$0lw)HuD}i? z*Vh-?c$jiFJ^dxKcUR`BCs!{14ej7)q-gk#Cqw&hXl^b~0M%wGET0{~6It_rV3@Fa3lFEy-Y`0`MP^uz)WX_=%va zMrPWijPB1m$H_CmhR~|?y}N0uF#m7B8H%nXIK?YeOS{M-3kKq3kayWSspV^;rFt%o9 zU)p*2GnAPycS6l4@mqH9&SgTW-e*{Pv)l}oPRi>!DOq}p9$mv!ELkSkmN7L!fQpi< z2#3Hs_UqJ=M_K+7N?Iv5))>m?5(~p(Pb_$#(5J5n_inU2y%6~=`VOKso#^{V7Cz2X zsNAGaW4-z?IgK!0(*|Ntu7DcG{E3BfE|9c|uPO>HnkyM5VH5v2zkRNbAgYvzbMlO& z=9v)K>xKAw-1Wv5>A16f->W6Qu0M-aR`iYYtpr>_6APWlsO^s1=|77tJ+<%=eU5Kn znYTHAO?2=Y{OnkcU$ZB_jJm|@@f9VfCU-A6C9(UiEe|C%1o@dh4cik<9%h?Qi!U&=@1rg7>#74tOW3IMC;Lt&! zJ9KSpg~mW0>k&zUWyTZ`mbLRgx)V00-mIM~DdY`s1x$KMDC)RZZqMlH0__ zTkPXTZ;!RX2s+7zar!_ZrWS$e2BsK||A`Rk3axoNFq6I5IK?inmmEcYP(pgYpkd^H zRzsWpKjpuJTd_FHM z9tp#qtBtzx`4joYQ~Jy1UqZtF%AdgSxL9nC<{sa$v&X86W_#5*)_9F?$WIj=7r<=z zu>-)D4;%8W2&wqX*A>M#Y%~bH+Wpaq#Z&c|m4}JN+D=d0tN9_fHKM1huP{}#Q0Qmt z{3fT)4&$+pUnDVoY9w*iv;be;hwwf;=Y1gWgL2-7^G@2SgJOxXLvnFY{Ry0@bMcKN z7OOv44a~J43zaXE2|H|=o@p^-Hr|l(Q~w0Yub})$ZrMTmB8lSxVL8C6DKWi&E{I$I zZ7;0r72j4ky?f*$t{FJywH*D?m2ay+n&aq&Jk)%hDP8RB)8OmYC-<%+Ik$M9UtBz) zxs2z`zZZ2NI2wPW#gQe81!>p^S>jF*2@ zq2A{J>-afpqPv=))q9(y|FVPGCPN#?|JuF9w@|*r*ZUjK7Fw!vvjWuH(mCpXFdlTW z_bD19e}Ny}#XG*ve_>4|zMX!sT{-EnDZr>|n)UT}qV||bGC4!9+{ktiNBW(eEtlS} z)qNdxc0pzHdVpb6CkR^O%BMdg6XbIJk%+tEjfw;c`J=!bHN2PU2_r?I@;WknWj{X= zQ_CM;GZ>8ZROIfbKQoqEyp=b*3XWie7HiJANGQhatmjMV2VRKE^UuYDEC3qHtwsvoNi!S>c~c0Mqm|E9mr4=po%&a6(X5>kZn)WVCt^^x() zPBTQ1KVlaZ-Io-H#vbRh3drt?IQknNoDYvWJR14!1eH5J!@2bM4mGAEsJ;^|mX9|S z4vyL#4ja8Ec>n*RLvO$SV*PfZLymmcN)PJ!`Y-axQ(tA}Rbug`-1jV-e#^RFOH=W0 zp}GvpUv`tm;mXJ;83RI1$B-ONJ~mBXxgeoNl#2+2OM^5>$8zISzx<9VBEkV|oYGeT zUjC-|_8DdMCf&%<>Bdj$21Z*Om7u>)Y^ZXF07U%Td^hNyq!tXdu4Wcw|0GM|-S`hB z*9_AUM-IJih$dsZZ{;*{>DJWvcAISk(oi7ji<~$_9SCtAD%k;V>+tRSvBH!jjxWqO+|>8so+Ejh8PkV zD}c6KD-hbOaJZiJfN1jO5`z2DY3;R#dC!1DH2=8>+eDF3J89>2Z;4H;_FzqGe8IkN zM19D|9MbsnS+Z#c-?IFIIwBf0-+Q%E|9iagT}FiFd$0ZJ?^*ptNBiTx{-Wn#eIxxQ z&^H{+52kN8m=0$0>0{*u@X~VP8yvi8JpYZK!GEV-N1t)<-*;$8KM9{z$(FC{7T>U} zL;F$xRMhV*ntohGXwfRv%%0eiXN{b#8Fc!Ap~ZFzFutMt@(tam96WPJk5vSUOa$5- zRm15zB{@KFbd^2aw6=HQF|_gZIsX@5@sYn>_bQEoj#<2 zzf2lbUM-#vP3w37nNIr71j&}3$qMP1^?YZ}JZrL7d z%N%z)OC@U`aSC%fJkZCw<98m|@(+%ritjm)67%Vij1B~f11T?JMaaM9bspMY7XHW;)~BEE z-C>8=6tPxbIhJ+PcMTF*+N(rBSbKk>ns`fZoBwruI5|Cn$zdlJ!=G?l*&?@YmahWmyaDpH``zTymhwY zA8(&uidnM8(7J!0k5G7wtaAp?x zHfC5{uN-;gut~U7)1;%{(6!E9z;wL+GjjuaN+!F-Dg^-{rHr<8!^%lphEa;S+;)R~ zP`P`xJxQxrWYH_vKI>0{ZNKwnV28Y+Kf7l(<48AU?oaiH_@jH~K-?Yw_xG_DNHjTf zs(^R(9@+=}C`r`NFRp>I$s1>Q|ItJ0?)l)Xe$I`CCSqplwwz*);H)oWP}^lZD!T$tInkPR!B2 z-idIEzIs)LCLl8ZCh8`Tbus{Coe+_P3q|6$lyV!qmJD~29tbPS#b6Y-I0AXKqXS=J zt&E|%_Z1F*=|6*fV1qJ#nc)m1jbrHZUSQkSw?iT;*AjX{_A7BD@9Do&fLw%krR_Am zntbP5f!qxEGD|6=XL81b_O^w!$5|=eRr~GaZhJLH z1kUZM`*{28)S~*T!cd=?FqG#H;o+i+P@hXGc(`mr zsLvG>c(}GE)Tge7ha0Db`rJH?hj=~23-xK#Ps9&*n`oS?xA=`y^J*(h*Yxi{Q=cTN zFm1SlTe3lTz4j7gjhRZX@&5#LvuUN?;_q4e*np2P)G293UhNUFzy-dT4#$@)hFjVSx8`pV7&j7eiG$uD6CtiD)vXx zGp}x`C}_^bq2T6vInKW8lAPCJ>$TX?i!;m=cl2gKWYOIA}PG1gwxOX_+?ArErq zpkqGUN@Vd!>nwG+{<@gLjxGI>#dgx<;aU8Z&GS*2_rZR*$cC zKP*=%H_v|A8rRt&{%q>&wAPdScvb<9-9qn$D{Y|EFtvvo_lK+Wotf*yz{ZPAk|aLE zDi5S={keSWub})y z{6P}b)P~3TYLNChl6c-*<{*^KAX0ir&FC3PMS4e4b^K219p2JVrcqc>cd>6SW7h-r z{hR6HS{Npr;f)*D6K0KzB$5>>D3P=kVB&95*CUC4I34}&7JIWOE#8TYN~Ffcn#Cn~ zR?ZE|h_`Ufy2}}Vp2wUzWc>TDI^4?Or|Nj`2U9D!uKlS8soM01<1SM-KBb0xhw0g| zr&J2Yhrsm5V?a?J)e8ObsLJ%mqZ*|@9$W0e9#?lfs=xIIK#tWiFz=BnTKNE?mpumL z;9x^qj)LiO9Hxng2wVQhyv8IsXr#Zp?EUq6-+-9eTY90+=WPNeJp+Z%?M3bwL6+RT z$mwL!M7(T!ph%ix&@twA(U}qAvw%#*S}4TG!E{yPmE&RJW}~CicX!n~?{nxSsM0G{ zHE!l{+djD_TB_`R!M+6yv@Gc6dQ&3~D*X{wtE{Ya4tu{893Uu(k=F_Qnj!(3`0EoB7Z zVx#q*^VF)SWhZZ$_&EG@3IE1Y|Lm{UMF;;I3wb2}Bh0tnv|rH~h4+hXc_p12IAB6= zGU=RVo>|0|nCx_HOt%HSX$sg2r&t^2l+&NRr{g&e2>mZ(YDQ;kOfPqrDs(lly7hAS zOogx80=2FUvxhh-J!@ZW7rbf9oA5;Fa~Ng&om=AlzKASde>&Z9_+pn&H1_fHZJN_*$|kW z0V`&l15DpfqdP6=5*0?*BZouRg={Z&j1xyjqpLr@?owu<2ob+N$?|PEo_w!}R@ou> z-}w?b`PyB+XO(Z>|IBBnob7&jt6#lxhHqAkFEc%;b*wlH+sn``-ZS@8f3opG-kBNk zn$)jtp!<&x3TghBWO}zYJ`%jOHa_Yz2PAO#F<@q07pfa8=z<0ha;$qTATjqS~AN$}cgKG-UW)c!%LyDiLZ-TU7r z2j5yP)SgmnyZamv=-xxOxTB7(RnuIqstW%%qF?XcOOPe+*ItAQGDFJk9^S!5$D3z( zmtPD)TdQUmyw-vC`Q)!fX4ZYx?(+m!T;mKM845d6Yye}PdwymKqAJkOQEnat*zlph z_NC^wX4!L4ddTeUxQLRO2wEHUsy`l^gGXCHWTxhnXZlK~c((59*a+7RkSiy&T5x+T z7CLpNZ4$f+=SXrl_Cz#)gl)n|4-48Dv6dt|nk4KfJzf2|4xkJ9fY>$vy8Csm$ z#BXSE|0&B?;&T0dW%)~?hObmU3y1XfUBw7CVzl~x@fbTZe3h1xjNP$XLLni}IXjpl ziLX7o)X9@j;|!iyI5$pH$}?g-qLW?33o8eYx89*Slk}FH_aJZeH}uA3u95_F&R!vZ zoKg)#^#Zqc9Z&V%TCL|WEM+6{7~`^pP$9A8Uz_d6Xir2C^+qiDVEJPos_-FX^pPyKk>pQq5G zGe)2vu8eR_uxVEkaK4swr$u;DQ#`F)bsx0eW7$!DMe?=2*CpK?o z*eNY)offxyIkfUR%tODZZ+=H*9%!0)0nKqU!WN{Pw$pE^5DuRgJ33A0 z!dlF>rLbcN`w3pYG5ov*fHP{B*iUud1@PA{7gi=x?~u?Dfebmnj)ZLdpl_)K$X{^Y z?i^wYK;U+@xb~DPFoH-i(X+rvP2_N+iM0w{Zcxa}& zJ%004PVAqHcXj~_k8a&Nn2tp?@$UeHn!8B5J4)-vwua3PqkQ5k;JQhkhu4W zBE_XZj=7SJa7wriu>! z0Jl|#4bq{qtR`uC0%Le;ZZN7tiS|I+uNdc-5;w_RAPEiW2_3Mkwumgx!rSRHz zT?=LA9qBVW@xhLTx2(653tO!5k%3tAh+1<~NkwGvi{8Qu-1iI8=THLlyq(f0%qW>fOWBta^fCU z;7z1%(e;kp31^{?h&J!-b|)qn3w_ioc^adaVk3~JE?!|QIZtHMA<4#iDn~hHeRvjh zN}Beg2r2G?5p+ky*b;$&v=7ESmYhLtQPy+w9w9N3y1G4*zq!7Eu2k3p#Y^yo1BX0@ zuBFFA^HxOi*WzkD{iUI68$jt~V0aBRTut#v+s%|7$U_KoAcTP?p`XE+zh;eS!UZZW z6yk8dSRvh%!}6aVVVt}T>FYIOp5cz#S3W zHe=7EB3J3joWt^+^D~IN(+liQvGCLRNSwiMga^O8l)+0N!u(L>dzmi66H9?Md}J|L{(8&wEolkvP;iVjJ@A zX*;a2TN9Qr_nA1&GndX7i>8usgWfW^-swAgSuc>R1X|?z1yx-s`p`iTe zx17Z@ogs&zmJKt8diF5*V;)Q1^zCj&u|@97ZlV5rKDr71AnLFu_4StQ>at-^*hm2d z?j&>Y9c=G&h5uZI57#=ogVRC{pJ4|i!bm+Q20{(*xfdbJjSE`^YQmmEx>wNT3&buR zvOaSpARYRzE+1=Lpy?n8L#cIbjQ!})?UNC-<5Ru*#&kkr>>x#aU)s41Yaos%Uh{+6SwISx!*%S37&nUET_ zh`&?|&%wQx3bEciu{-0Zg{szYPaX0V!AfMd3dEKlHgc^mtf~{<1g}pL|0N=cgcByA z6d=KuP-A)I)*7VzRJ%fAha`oYqG_H7Tx*RxrE3l~rI+CQp@ z7a6itHDK0X$HUMUhH8M^J`VX7OROPWS|oL$-@AjiM$5N{Lw7$PJ>ZpSDk)hJA!N?4 zmxmU;prp{_*hrR(M~ZfVuZAMQT0{4)h#c^iJb{3HPp*@+n$S{_(Bp4K^WTb$(kip= zUt}u(9+%4K0nf)0ZIR{w=@A>;7CGRf=-}@HiCe8p+v$ZWbz;wZiz}7Odx+l zgG&X7I4vosbSS-!pXLeqm2`q)H{br2P2slk3O}pHab{UCx=!REA2EUkMpFZZM`ryX z0L{jHvA936(3o!s#TlLTmA)`dDJbXR3d(7*Hkp~ZAknIpK1jwRZK_Spm}>KxiYl3K zhWC5c$O;^5EnQAa1r@Z`v9nqiEC1%2pJ(lfoJ5ZeU89>#zyC1OV-+51k>xwNC1B%8 z)hwC`Ifv3fczK4+@ztrK!nvVErKp`f)SM+ePq5%#9`f#{0tezqA6itdz^=*;ZbJB{}VE^@$kn1|DMF;RyVmi32&J4x6Xtl`n{SSj6(REr}rky$32 zkSXV*-;rfCS-b~iJ;)VI>yQWGWy+R3za(|WcNX%tFV!UHPNl0D=Y5h@1EdU84PY@i zXFusFoz@?*Q6To1L{`W8BXi?7lEL*b2%0ZF^=160%eL*B`ho30h6seZ4Qb)wWM zU8o39+Q!Lrn58LB=HWrbSLr6}*{&d7!u z$1sVsJsj8vxz31or4I+s%o(hM{q#o=?`=$wnV<2G>@Xp@T;fg{BI0a^u`7IbsPV+_sqVwC9sT}C z+(}cNGc9Has;5NR{nNh!_niLhj(6id}7_y;;i}@k?dW7QEs3wmm})^Pyw5*(Y~KHxa^F=3f*ZRf>EPDrU}jPu z6wfOhZ*BDzVKNv_<^_}yTD;2?mOT~HfYS@WK(oOZmTjY{xtN++iv88Kn8nZ*KU6ap z3$n{O)q9W|*o2iofnjcG5nlS#=zo$;UhfYDpn91xryx%oW>eEksFJa?j%+mGEGdH; zKVYgD^o6GJfXR&mp}~RRVY!&l06rezv|^C}Y?;Ub=mdd&Z{)gpD)Yr5VA$9~ndiik zsA#UPv#VJ}97n{Il30GrDXF584t6Iv82+hgda9;=y9_Rxg#ktUQq zw4AzANTV=hj)Q$W=06T!L$~x7V3ujKg+o1nHhvE#EoU4&0^@=4@Ae1dI@Yt92<#v+ zL+ci@s7k*AeE9UtjYuX9qYa(2|H@^*P}z@D_8w$Ux8wjBmk$_hwG0>7vhx6|qBv^! z1B6N!I>EIMAARdB0|^Q5%@gE<2vDYx+nC^T(0=n!EAX@ZDDXruBJut2c_gR* zkW;udxN(r-H9GoB&ObDb9^wQiPOy)OlxO2xV4Xj>u&D|HKf`R z;9^ar?}-41xP(iU@Uas5xr8r4Gkvl|$6O{#nm3=^+mL^>WR!r%(pMQzO|`rAy2{Zb z9CC*Xxq>cz*SH(V(f#;dX8uf(>0P?A(pA(B!+try1g6;J%5wm|Q~dd~tj3uu9V$<1 zrae!noDV8uX@!T$7!RBVssn_o)E>qz1^$)-y@M#qX;dTv(@!v_TQU9tu*_byPf@L7 zf+?x-uMEIUqm4C*kw(?Nw`xC{+S704bht6d@7>bz5Nn2s=ZDXxfIiNIrpb{XuzYRK_9imr@?f<91Wr>vWOz-EFHhz_EnDj(SFe+R`BKwIbZqz2_?Yh zc;%N-gYGEx7EVS5Z5$w-v!!;wwzISHORXFJbbI?K#nK2h-meTK)qQHa@#~o$Y&ZUC z3Z-zsgBl35|B^zAb*t&JX!dLm&o;p}>ff0-Me!SDR z7b!oOCH`0W+2gs|H|NYrRYk7&F#iKCQ`jV0^S)22q0}xWxs>85Z&80*nNlm+<-{;2mzF7W(=7p{^*-PQ&XU^%I1E0U zVNpWuOOK|ofRDT_OX2&==*IMtuGv?zJ3(y`mpwuD7bbNTx{H=DzehIi--f zr)9Pwc^jEC`NlByV8G^^{Kv?*n&~$^OuK@qe(&#zJB5#&MGqO6voFgYn=ESQvCVZ7 zg{eb{Yej22pPi3ymPNyzpcfyTUMUe1vd9tHebEPuv&=M6Uk=|*;5~+U9?w5bkA7% z3b&r_DfQ<};o)2lVA=)4*h~o zHR13ZbSDUU>mKk*pNXOtnC09?^OdS%v&lE?uACc`nOK8+qdQ*lL%bzK@wi&m{!Ww} zd>0boo}BeaxoQPZ@jE^Fq7&D9sLn5`v+Y(Ae~@}KAqP+a>FZ~KQL5h;{eZldMPz5D z{P_}Ch54gBeNv}X<(Tqj)qXamwAFj}RU+QA@=p9` zJ48J(5xHZFIuqz0Ik*AsS-wBtMiOtNe{e2QlU?1%Q@4@YOP}tzFfhy$AqsyUmMP-3 zPpmKTS!Z789fVGAIFpG(P_Mqn%#g=SkEc7p-$O(*b~ip_*%q$Rk4`5Ri#y8iU#Iub z$@Ys!tKt^^Kywft_9Z#bG7Nsl-;E?{3|`EsUVC@6Hh$|T6RPDb~9j%Qj zLVq3e2!gg`-wwut{`WA*>9}FL({W2r;}+R>G?SReq|X;>-GgjSSnEO!L+A(UXc)wA zFog^nVB+j!CQ_g&?vveuId2gp4dy&6H9P-+@O+RHIdQ~&rkUsVHSw+Ob%!un%oX0X zTz)N)urawnW7&J}`rQ5&UW2x}zIhPnz^dRj-s*b9x3a#)``4~?YdA*_H_P=<{TScc zFVwJ|t`kt>I`yHOlGJCAT$Cf0smPc$^5oZcQvtO%v6|EO%yDJ`KuX+iuMgU5MK+%7 zzK$rnL6pn}zKv2i;JO~1Jh+dyDRTqjjc{-mpm}DVwKClNYwdf`5&J$_94_Lc67PP% zCD!Kjz~`=zix9V&>#YzlS7>Xykl=+-vyOTu>q=8+<|ihVvelJRkZ1b;7FO`-=g3X3 z9og6KHELmM``f8<1!PEOGE^UQN~j@2PIpKnI)jhz@tQu35`vI>#sMGqu`RG4rNI7z zg4|xR3Fpuvi|&N)<AWL!WvSkMlD$2s8h#VF4J!XUkmq#SMN3Aa+cy%b{hW5va43kS)I zmtG7uSt9Lt(otX}MPxpr?f&?6-ke}_8x^GAq~uJgy6iR80q3hdHpBeQ)iOx6JYG#9 z;!}`WBtWPkK#GaeGjveCz?uPbw=l0_2QKF{4D+SrF^0;jcZ5l$AOAr+_;*tlia15> zFO0_RmuKga7K9`{esCzUF!Bzka89}m1YAPmut=&|9?O9~B_|uSx>ZN>kC!6GNNZeuRajVm*amq;${F9p6Wztl<01iS+(`cp`OkP|i(Zs+(`8n_SrykI^@6t9!MvQs zn{{1#`>Z=ewTh8K!J5J4RXIekL(v^Xn35P*6yM46t3O%Ul`RWt1Fdvv9%W1kT~!>y z;uK!OOI~O&-fBwfMUq|y2H*8EL@#~)FBN*}=f6zQOMm~RMlbvLFVpn0pS?7c)l)_8 zyE-%X{lPBp3%b0wba`LX<$Yb3cM(3fd^H$lKUCn|^t6+ozeMU;&o_4CDM#N*75}QS zTL&xP_}-NP{<0*O0S*V+X8_otw|i6lr~m~N?Y&o?TfXF_J9;y#bt_OZ4tZ~*E^;_a zbCvg!o|ExGJWEj25^ZIOJ-@*5;e3Kgb&+rGtW45Hn&A+3KY&cGbb<5Z-wZdQGF&xX zt>>HoI5|g2l7AD06+k2KFGqMql2?>^BbBM~OZMASch3-BIdX<`s)3xz^0T$qpI3hL zF8Eymmf#j+IW~H0dt}c^Q2w(F8sd)vaz4B8d$oMelBV#dICd&S%H+3m)y zg?VR*=4?M+gB4#<-=1IFYiJ9GImzz1 zHM;Wzg5O{8eSv2oSC}}f2Y(! zPLptH6nCw63yo>@@v!e>e~fP|h;Qwt-SNE8Xufr#r#ZLPi^t%Qy54r*XZc&TyE9Q1 zB}-9fHZPH^u=f7s`E-u6B?8)qupz#PCpJFsQo$j&{^@g zp-k5$U)~q5s;t@}x%sH}C6wB>+u{4T*W+2$OYZAl8@i?KCBJ`kyfSs{p8(6SDc!MO z@$5i=bM7aj+|mG_3<_yyb;tE*_^folzJXem>i0o6noLNY;>ncW{$g- z5L&!~#7gw;VXOngT)7(mPhos}&(NH2G?-Y1gccED6#Vfo!FW)ad_*T2LyJ~&L1$rQ zsM6!$OkD|%CXEM@E{g2ZmNm#-XiJG4$4lBCT}XU)9-tD5C2@+CgQLxZu$6m5$)#@eBh%vuGv`sYAvL~GZhcK3Y0`BroAo32%L_Fsf$ggOK=P*j z49TqspZM09p*j7?I4(6HUl$rQl^7*JC;wH8gs=U(r7%I_xl#2j_(Kgkw>xT<9#fCf zpQGyE=Fv95mQLVZvWp_}ybB-JzRmjdI=F*GY2)b6sL@M{f|c@ZW8m`>JI3=8Mbiav zD1hk!$`|_MnrnYfo;l>95R0tqiq9L}aqhjdXJ1Eoqt?D_7&G&<^<+F~&GI5IOAiCV z49j$Xf4DQN#kX^Z^=&`4x66a6fnP9s08Kr8Fc@X7B3Ce8W$qs(=7%JH8*fDy1>d&{ zSt>jRivHpH1^_rN*&6WFX9W_;9jmjDdu7Q<2tzJGkCeX}YWxLtThQ!(k~e)rPDQqq zI9RKPRKLrp%C{qZQPI_o^xi|D@GebudN6E8W7dLWdKksER!pm>=#0$RlFv&I*V_ra zVX|Nz0k%c3&vmMr%H~Le>i2a4jhvx6k0zgWi^kv-)p-ep%*`254bxx>%A2P0;*{6+ zcQJkXGaemx_>}uCh1xoh>q)12<4)FixH&Jp#S~XguPa(Zs3F3TvpYaFP$U~7$@%j& zW)*Yc6&t)3i%)e#-8C}US#g}Q1qdT8+&+C84#Cs-o$4L)rZKpGrT7%fUNzYo6azMz zTBf4|-ebQmFc#W{rbLrX6RhgGyktovIVYHa`nL_};6M4-${drOi@vfpAK%%){MUS2 zzAR&9I4d$u=Q5Fq2b?6`WRgNavu(aa6i48#3oW`!0#U_$zg7~1(<9U3ALn~lZ*!^~ z_rK$O`XeMN;7R0Y?CFy5ZOP{;eO6BG#z(_?8y_768dx=DkNne#s=R9Q(xLP#aeTHs zmtVJ+4Vp)a>Pn4E{*s4c5o*YXR@sif;*Ty{Wim3YN~iiKgKGL_)d!dxzp%i5G!*Xn z2kQdw1Zqk*2?Erz5Kr_nh&u(*ABfDJJ8TpVBRzdL9Fw`y4a)YGx&f2i^3?XdZxeYdikGyFoxaUkzT0j(TiLgZlZ-4KMB~us?m=?z5kRM`X zR5kuD?S-7zr7DH|ZX5xqI5z0gvFsK0oQT;=B}=YK|!^E+~e(}TqGe^jsfHlH47 zC?I(ZaE3fI#ggwWAd5|4S$uzoB{FkAYe@<*#O0n(V zzZ2hCKnN@J-|ycBq&b|Qt5G|BoIM&9(JO&Y70yp|ql~90q^oL`J4UhPl~6K_OjePQ}{qLyQ9-2GmvGa}qI z{aGi&i8uhkIOt*p)oAzXcXL599^qa3w3EhFHA^di)AmAYfv#Tm=3l8**7E{cXkT#Y z`%nQjW_EmVB2~4M{%}Y75jLKYht%blalMU?Y&A@SuA2NoS&&7R%T?3vd52~{xZ7&1 z8YcQxrCzU&Os83<&%Em|a?N|aZ(&|r%-7eYXB>Gz$6$jYmv%QUzVZjSz3K#b6wF8Y zdFPS0Gb_JwzlM23nP`}^fp)PPGwV4KpOZNm(}O?) zhS<8@A3NTQ<)~KiTzzPGXFLZxJXev!yB}cR-O}kpYS*yN@E^O;`D?*nA^3wB2)X5- z*cpDEgP$V!QG)*liIxjL;V0pb6MS#Muj~R}*%^MmE5DoIKVZ3^xw{MexX$oX9sFC{ zfPYNz+QRVu!`2bwQsXUrRy6UN9|D+wvz3WfR*)DA6+CiK4#T^h;>4%k;>nnM6C0z6 z=e&_;7vKX=>`dOh{m*fX|27?^_s4m6i_IDZoV9U4dcdFyg3qBw?Z!V$M|;2TNbLr=l0F2Hwy^X>_1n!syNPTAlRQ{#{P-aOa=eAdYy5BY9wS2sA1VUQ z`2Q0hcHYHhJ&c0%+@Q`%yy>5g|7JmZGSjy73@U~HW>AZpoySpC+ugbS-P9Scy&YaB z3$J|vwzv^|&3@L_0IVZ*<{va(0v8sOP%{f$aY~9B)9}$Cyy8?rG zK?}Z)L?{1~#lOC$n@PYsAS6BUFt5vov@q)(!9T3?ufwaYI@LUciO`oPOMBRt;`2a_ zSa?}`N^-&wRMjDPp6{dmRnAn#w;om-ihE_UAaoBW2wvJ!q)`9t2=uKkUwv)w#J1!u zMQwlg+tUgPEGvrJukNO~huVw#gHC|I_+Og|-7_CEDyGc+NqbDH`1!-TbMoVV_Fp+znEEi30TDb3S!Kp(T!b+K<* zd4<>Qo?B2*f7krN-{6a;178rj*9!0G-?)c5QW*NRU#H0y&$~Ily`(qEcIx~WMmS`!q=5sAxzTG0RP{k3Jx`L%gif@uLhPO{(ScLp@`YiBT>q{wlh<$a|5_5e} zY*WtUXo2QLLidDQr47>u3RN(_XyP4wAi;qZEB^-q> z8Qr}50oZ9&XC&EkbaU)Lj;9nBbSX*vh?U12>c%@W$iI%Yi5GFy!jo&=*+*xc3;r9A zApb92{#VG=_AK)b%Z?LBvJw!?2#L*yn3$UigtrL)26yw@{>UyqPA4^eeoh83I8l(d z8RXqaIo%yYsb>htI^Rki3=pt=1zTgV+Dd;xW8JquaPy~yq2mB+uduQEma#`*ORgH) z@<>H(Pk!PvOAiZUqpnP}tPGze{}rJ$fFi?ZrqP%D`cnNK#VymcNV&WW_ck4+bwc+@ zdYyq6y&8C`FahucpNGuUzS`;tv|?Go~A#Q-kE4tlyi6s}+Q+Kt7?c+V>;0?vJNT&`rU6Y~s zXULux4OM*=%l|U-FwX`*wB0-40AsBK@!?E=0LRdBZl?~dPFUk@8~6RAeanwm#wrsO zm$C~Fr56qWD8!UJbh5X|)&evjT2kO3(%ysKuU z4novk!70pUahAm-@ruO8^-F}0V_HhPTqr*0P`rsEjp-(MpBR0|*7)$vRe2l)J-532 zi_mQLmm&RGHC)rh{apC1Sb?0$Y#Pg#Nb*)y$c;Op_?uMtNKvTq4-k`Cl6!>vgqtVX z()UJ^R7hyiUzMG%gdLDWvGPwtO}cL_RDa_@=;S#%O&k)i;r)lJ^o`y_TZw;P{%vS>r9(Z& zu`omZ7~XrJ&4x91#aAKH!59PkbK&NbcPf!z>HQ#IMA&z74z7g=A7I!nzTUu-uL@xDh(@w9-ewksL|w}v3$=C-VSZ4Un;i7hi?@_ zK{0ts2+0w@sjNTK$?stXCgEcM2xb#{{vJ*OGW1($r}sYVP6kILIoH{zi7fIb{7jQ4 zXeiysQ!K%v0})uA_$-?EH~L-Mf$%G{N&za|&UQ^&r!iY5M~+dB*F@&TD(~Aru`SOC zdOM~y3zgkXW$7?qsegCsw~oV@jKvSSdlNw;^B7X!Uw=q8XnsoGW!}JGb^11VQBxPj zm%Pg6YY&lV&ZJ1yIM<8G>%^Ct(=i>==w-A$Xfz01N~P32{|Fkrf%Vg>Dz)uP+Ma1* zw5LxHIQV7RKxcf&@JlivjqhO1_Bh!xy399{>=Q}d%qis0wnh^Q2Qx9Bhl$06qy0QG zc)KofO}v`wRqF1n$n2)_v7Kkpv0=R4mETEQhSBnuL$ljyRPHd`sHQWPmdI5n zXB<{02v);D%=CiC(?@h|z(7i-0e{Askp|pG1HNL>nR!_x zglP*+*`f3umVQ3zvBZA}g!8k4>ckG~%&6qt4kOe$L|RE?@TMpmmrWUxpk^#_F&voq zLVVLdswk!3_{_ziNxa#%xA)E;*cVtdt$1{E?XaTI;)R zJrcJ~bvRvneVO&FMcn)>>-6R7SD$YvZ49MR&`{O&n#g@V1!SdG@pa8%kn5ROfUxgo zf+1f-8@hJN_onsM7uH@JG-U&&I?;HdEA-#^B07nGuxmxA=`w21mR=N^b1v_yA)jc7 zs7K7QT>|(cZMgZmJGapfU0c6IcShuenpeO&mf~VE7S*0tzeGZX7C*(m0YZm5t&CQV zatMvjB6Lrgku}t`lA^K*6^7>ggLff>bGi@$J=NsuA;O6e$ksKLm!PhbvvnQd>iP&9 zg=_qvpsoXe&#kKu@2ZR7tvPiOPF)H-Z3*#XMZhO_Wy{~@#^FrL_g=x4NLHe3#8)#Q z7bxSxH1SGlRtjOA8}kEPCTuWa6%g9ma>1>oCVptOo29>dKQ#U$SJ*>gPwX90$D)4HF`jy#;=j;ZH7+IATNl#%1X;I#GX{8%*?Pw7RPPc3~wdd zF0mwa*^EesKW8IF1HRccd~8X6_MG7z#uM${)*9r6JDM|*r1W|)u_duJ2ZSDl zq%`P9RzBW%u*eK%Z5d3Qv)PLT{iteY;|v&UbjQ@WmvUUg6cY>``DeH;o5H>(nf?@H z^1d8soihEDj$w1%X!QUnxv|M~xS6uDTob2=^!?(R510$G$)A8#I-%rMxyd(b^?SFH zAJ0wxKP5k*3ea$ zK7q_DXoTIEK`D9{CQuoB;CNJz-s;~$EQbohsWVX#mvgIF^Q6KlRf)PHJ0fnqnbrb1 zXgcJmVv`Z#yulGU?|}XN0k#MjcyqpC{IM-PT8bm(YeG%G|Yyb5t;icGqM0P=yJ9|^1O*mJhB|Kkhg=5f&JF^^!o%12Cgq;rA|pkRf?mW7tyLA z$35tFeZivbX}5orjZ!`9i)JdROrBcOY2RpuRukI@I;L}%k@(CSup_cpst?WOV7;h* zF2~57-7eMdVruc88~}zab#IugwylyTev||;YuMmqSRYX#dkCzY{-{h=mrzr$P{S}_ zdFm5tddKM3`zwTAW#YxiMMZZ;@>ieOzAln%tOwcj8AR}M#PSddH1gAdKBet)b*=da z0hi|u^f8(-HjB|{_TRa9JvHG6u5b#?xrJ32m$0K|@Q_T&)m+A%R_*nhnYY>rkPmlP z!t8o_#0+Au>ODRjnekhJ#%Gl9xYvQA&P@c=peGYM+wan@whPR6$G*xB2gsV%OXm)f zOI%?riFVk>nI+C&H+hY-J-Jx`S0NLAsgS$F8a2cDpsVsiItJ{{-#a#Frzz?8=rzYLz7xe+ zOgePlAhb8{y1hH>yOm`#a`u=1P)5nKo--~@Y|1g42l5-LRwkQoV`o%#335m53N=Q)Q>E~N_7bR>nLxhpnUT$ zCqwN-Y)izQkL}y_eC+bj>@N;rAm{(9Dzx~fvZ8QuKpEn^wS?D=TBVmS4>jI&kTfKx z$Xw?nN%}xW7zFALwr*ydu$Pk~t@UcI{%C10ex_7uX{~tq;D_JM+Zf$phHCyV`rozw1P8kl4aq<1L{ZGG>os_to}Z}Ciwm=p)%ez zd3QcLUcqoo4hrzj06Oy_imAU3K-X1Fb)H0vrH>?5Wm@>EE}a~A?+f(q3ys5}lf$f^ zGb1ff3#5XqKXBJab^kEBVybdk?r7 zL&TR1VgMilPCJa0_>$r7ZH(TM^%WW%%<@`_4~h^DsRGcZx+C?`ZRu#RjqW_wCNR`A z$QQcdH`f(%3zvT{Q0ZRLE@~Ug@oP~>XX|S$Rnrakn^41-dx7#!g1G*3e?4>yH4H`K z#CMj28h=KmL|k)aR@J!uEIJY;cpM^R^pM!#_0{b>-J(lMO`0zlsLa(h z)|ZZ!ha&jX?~1gkeixz$GFz2GQ}546USUROJQd51uYa20b0VwoVrY@r*da<{iH9Ub zR^^qN`1l0JAiv&j4CC~`u4DN%gg&)q&@;W`_kcH6zy+%C(wkiGKgoMKAKW@got18} z_@uJskxe=JKa;I%B?Buf0)Bgdx=1eMb}4<=k&cJ0fA;+HPt@IZ~8(q zc53Y*&Y|r&-1@w}tNIdSp{r^XV-9-$22d*^mK=yZCOen@i{+Ah4HzM; z{%&KO+Dwb)HEykzvU<8>3 z?V$gSZs-_)5jv($ogiwY`sD?Pc~MZw{0k$MYJK`O*W1tWp1z#{+Nu2uAsl(1gA86@ zvZ<*~rh5lO0-3J!~S|VP(DB?z5!`E0l(+E_y7kiE8?#N{4M&d+IRV#ynMz> z`bFiWm$TK(bvZvnarTZS50gQN&zZEJ_4kggGk@{l*ZTwGH^KYIj&up$$*UGrC0@#nzfYLW`t+u13&|=>s zjDkq{_RyTd!vMEf%TvI<^XX`2#NJGcF{0yhO5zwTp=yt@V-lMp^HE{7;%aQ5o$2qp zj?+?_1nL8X`lYO^GT&iB^!K~ny}gi<*J3-X<|7`T7Qw;^Xz7<+xTo*xk) zR?m!VJ@el*emFI#C;T*Jsy4|e?=nfdEer)WkEeg$Rj|+A-DputcJG2xUuJ#!U6vkF zSbR_8IRgzXO=mVTyi>3&sk=w(1FDc+2V>wa7y@ZEemlIi?0@+)jLwW`u!S~fne*?5 z(oa3$nodKmn>)o_3yR)~kdIpw+-OV#jU>+_U8TVvdRlub$b&SP#{h38XNSPc^dP^c znZPd8peV4?IoYy#R_iYzom`?_Q?EA`e!Z`%MEe4f9vT1mv;+a98R zRN>q1*YD=g9rN_NEp$hU-^%3p0`M3sQre`j)flp0TVEfeaOeeZ=&p`7vDEkid>+QI zmuey6(*+s}oEw3oXvN|nPpD7*aEkdR9J(sXEtAa=UO@D+1M!h4rh)iJaP!c>P}4-M!*fehBjV!f?A4HbQ!^^_UH$`Wu>Cjg zhm>iQXtQ{a)a_C=Vg|PRld!X!FmG?2B`E#bEhOHV?BFAED1zPYXo7AT-M=z%LrLps zq=P=0}PVAg=j$26T<3Q3$NG8Be;8aL`lB` zaiUqeSUM-8%x~2(@0e6hqnmhV(bt)~l*vSkzaFT7#k4~CpQ{mB%2_E)8y-nc9s<8f z?rPOxrKC98@xW`wKDf%^tf!dG>KXhrQZq`t-S8Cm#qDOMKbtegWao^9PU!Cgc1BG$ zJu18k7k({k}o*3g9Mt{ecT6uwd>|odmIP6W0PwV@p|96K}Nxjr%Ff z(3p@#$TUncBhHZ3k^C%&w z8yII-eN4-gkrRHWFHJarbjVy{!8p3T%F0IS1iSacKL5a z2CvYi7ef@{`ZN{441`S84^IxCooJ1JhQi;iB6QEHczZF5TaUN!0;=s%(SW=n_K`x1Ux;FbzwH67yx4D3x(aQ4igGyQ ztaW_T6LgiYQ<^bd?2S{3Cddv6o~-I$z1Nq~_@`UhaqT51)`pjfQ=tOxcnf`6ry_p& zFUYjDi0mb}72<8n>35{DJZ}a?Qe$>TnYWsbVyecZa{#Q%h8SNk@;oOa&nL0L|B05r z8)}GRFGznZox&fMHsA}KxEa{X^n*qQ{M7CY_@i?N{F#^2v+KX;q&6%vwZXb;$zcFL zB`qs+2)cLt#{QfnI$NRgQ+m>UGJCWMDzJe@LX|i#kR(x4+nIN7dC7S46lQDh3)+%7lnMm*HhNajc4TLv zTPGbNxaWWa!>YvB>HL5~fNX{T;if`?{9a@k1d>@fc+zDQ{vt@EH>>2_#nE})E#r&K zbYA~%K9@hBCd69~u_<@oz3DH`uQfukNOJr^k<<+Xb)G@TXA|T4k59&q+&V518?-et znEzH)=6lP%!o>1#A`fM5MSWF!b`LOhL*@0g*6uS^=eN|EIg0wcOJ7&ZRv1}jVT9pE zjK;HUcb-R#9u&Hxr_Cu}MG|j&`@N}x&D!!Easy$et%V_lw8hk($240=cZVh$;TvyM zv5>EtT#c_?s`w}X)5`@TQk;^y{BX0eRM0(^ma}b1y;w;{5ocIs-q~>aHG|6K6T)Fd}UC_B^`B4ZmqwE@~w`|n0;f(V?^Z2 zpdB<|4FiCxj%DOjA|2U${N4*uQ8d}D5;@Cu)+3s~>EX5J@tD|0TYt7Iaz2mh`JzZ_ z+)i~o9jZOg#!CCJsH$5e{yBkM5Qny={TazIj$=3;@!>%^hf+BkgkaZENAmFea);rvMfC)Xq|QJct^ub zH@|(}(FI!aQ`!{knj7G2R^T*(KxS-WDs;jW(!j0QHcIZLIAXiB^>yoPVARHjdXl+B z0xSOXwn%bh88mzbMs*@Id1_7K&Ls>kDdZ6RaT)}zF9r$k$$XgV5=l$AkZ+rFI(!Pt zYT!l!C#GrwRP#{aUz3<;$}L+lxAEX}JbgSj=;K{Giv1*~*u|XFrPxo4U9m&_Vnd5< zdYkeWoQ3w}NM?RrpDDOk#@BTZ53ho~T6Q=j)BAyb$56S`m3A+sInC4fp9N=Uq5I+` zv~$u16+x#|cj}aG`PR;f6yg1WoS8{fW$YK8wJjfCz`7TGR((6C87FBR5ICP);*MXD zF`T@zmvyEtO&kJjH2LfKj$L2mg0a4l)L6QUjgz+^nCoV)b!lA98*zySxm~;dh%qB( zdJ4t=MxM+>3ZxrF3}x_?`mVv}C&_X$3RGYWIBW{@eUD>*ab9WPsl z?v8-;o)rDQ`~)}_kwvm5-BiSqwxw|S`jQ^oA{Vjh9?2jaP-cdy!x5F$sgXro0>tSH z#s;B_YRuKn-10`2`TJ!QQ%RT(R>s)2dLi;Rnp94IB>gMZ?>(OHUZT2E6p z@{cGM>rAo26~-XnFwVR?AwuS56#!ceqUgL#l3{6ESSxt*x2>AaVwSdc$bLx3)W85X z>mselmTUK5g+LHYyMAOlTaBmjZi;(m!M8$?X?0+*j*R+79`#$Hw;--!~D#Ea4L7ecd#NP|yBO4Ei>7x~*eIqRD$UZL3xR7W^e zYZzf>L4E1-o!aO|Hg2$uZg1Qdh`B_QKAv;7Y3a-5(~)RpD;%G%Z~j!({IH#1VYkxl zl6Vha%%Gs`{f8s2X1KnyVeu~A2CXK7g6qBe2^gCh#HdPNmBal8yMkk*zzzbI_4=)> z6s8IIhY$S$x46^fe1@A@x09)3z@0>f&I9ge7ck(KPz0*n=PUxZQERyVX7))MuOyq#=(kXWUFFO}$i{Tv9KmSxEOH~~9V8PJYJi>tw?dvy>*!t2 zr*Xgefb6g2EZr>o$4^;z{Km4I!_@lk>5j_*mhk#Cr#iT6;SUCV8PHx2bz3EH%o@d+ z7olmoch_CMA07M%SNdHb7pL^j$X$IN$nE$yl-H^~t0&pj^Px+C4fs0 z=-OlB`A(S$ei)wWvDZ1V+PTM;okM4gBfD4i+0J%s2-pqABqtuZV{~HTpdFcuSYf7L zrNy1Jnd9LB3Latwn}K)6e-%7M1%Le>_{Z5-3pFnCaIYCLwKUZDC{NMU49+=xZowCH zGD{0F?+h?7bGmsaYf_&D=>NmmnZQR`B>g`j0fL|tR?v7y4Que)ps0zUW+2Ejnka}M z2rBD=uE&Zx11Q(PWFX@>$f~Tzda$~#y6UbcW>7TY3Wx`aD4w9}@r)6{i%TW{@2~rr zBgp@KUq2toGtbjqU0qdOU0q#WjmDz)MiE|Lnh~N``2yu6*Egn(E!Z5fnEh3WC;D!o zvqN$y@4h_>oGuVfx|r+g@60e`cltaajW9hNn*5s1%KJAA5Hca}*Fulv1Pf2MNLZ!V zAV_-yDf#ZMqwuGn3~~0RK2(=8Y&0O+Q$3*S@4Qd-t~s1FgE$XmO7rh*Gu2~MKalFF zM<{HJ7~OzmP&K8Wv@HIoDJ@RW6StM@AMM+FePc0vp}OR0X%0&elVw(<1`5khh2?>i8_4ORV|R|z zAlaEZ6_b^M$4HGml+#IC-BYz5r&e<8u5$7^M59FOmW-SnFTC3Ak{l|$o_J5=WiY$< z-0W>m_WBl_<}QC+$_^KRk+K<+_V5`jsb_hv)R5 zqkmxZG($Lfm3kh%kJsRTFCeqJ%H6OTu;n?D;;p_`3+~Qq^8<&?-DigE&fm%ST9Tu%ULRe>t-lV_ism{D|f}y{ksQj$0tl{u8hlksB(oLO9<)E!xgKkK^LD$k`q4I=m%P&(oH3%+&QBcwkcc5|r~hmyGk+75nT(*N?n2Izr|sJBxvd8AgH03RTVcvLHPKES z&Q%lZ*HC@`UHjb(c*wRMM7@3=@f!?#s``AYi~4s7%;sG?dKf|mn7a&^u%@038+WDt z8|MIKl&Tl+s%Rg4+EgE9vABckf2VrtXcfMH*R~c|Rvn#fEBKqXE>>F`-=_NP9Gz-- z(uiUN)s0|GkF|6-L2Wfr*i3Wbc1wrt-`KZftnfTY8A$n88u+>ud_#as9=5BXPJv$l44J}afG(nN`vLm+5U@Fs>I4;l&_|>M zK<6+=3;`OIE2(UVKywoH$%4?%(E5`g{J7fm=M;FC47Tsj7EpF;gyluBz)UeT^f;7C zK8X4;Q&Z|X^9jFAhjy}XLCW;tSwLi$k=s}jx0i)4&jy9-K*5O9@$En?v>?W}1M&QC zKs+Q6$J$<8t6uD%qeVGhVyrvpQLf%hpn7sJ%r~T>Hyf===*mY!EcaYB&`u)^Py?^O zX~?vf8t6^~t@jy>FK>tOqZZ?rk+y873x0#~cV_``3IGj=x^^IXS`d@lfoS4Rm-ck~ zw?I^-L1?{dus6bf8jKhJ+ku!W5bYHFRRXc)4G)W-u>GSh@W6}wj(G128(im zcoq=p`59s+?}R$3(c2K~xx0>mNmfDJZ@`){@TH4%T?d5ZC%YD2_=LgXI$Kx+JgLGp zDtywei>O7YbP%qwg=bLs77Di)_nUNSN=H@iwCi~52K%YrG1FhSPSxAdtDmYbf1Ti<(#RPEb(vzE5bS6k2QTK)5{ z4XWp7t3UXg>T^~70IEyCvXHZ^yjBHvyyo$~wVn9Pu(a3?n%N4cs*Up83I1q-cmWW& z_g_n1g$c`$G7U(5cKj$~CSF8G}Rk`8H zb8!L2R%eop=_0eZuQu+VR40pmI*r%iXkt6Qw)d+h0n40vta&y&*&$oZKIaF4#8AAQ zH{cQMQRaC0D`qP_hC}p8)jHqIa-I#an*pYSR{BE%Fb-F>tq#O{lxcZ~LyNt|50rWe zFp4LN+nIP;rRNI7ej#_zC z`T>+9fZ{&-Uu=zL8~3L*@wS|@)IZEl1ivt#{foj8Mn(&iXw_BTrweq7;;j#*_v?0( zKX1l2j~Wtk9{*B2y5SKHi*)6L>&F|?&?z&S*5E~DTB_U1c zI?{q-K%4FP4R9t9e>tZ~~Ogu#TzThzmzpyLob9kx4V9j55 z^;h;N^F>qC8B{r?j8(uV0vlU;W}>h^UAzQ~GTBFB#fm)ohG{}OINIr{Ejv~hTUK}} z%HvPfV-m3G#=kbMc&|sK8wcertS|)l1h1iz{P|;xHR?9&rP)lwbIqPuDZlAxHSvmM zLBPInP;JR_cD%Pad6f%f=I| zK#NTpFQ>8@IySPk!fBbMNJCZa!&OX8U0U?@y5nlfPBXt^+t^o*wQODArDfzOu?W^R zw;iG#?gRa?ZCl@~OLW`IIPO~auyW&D&?Dcspl`vUJ8BMH-sO9L!yWkwVl+;96RI#% z4NhFAl)U15&XLJ?_{ot;$p{%F+8vp!_UMz{Y&=l@Sw*V%%Kv+#>V$J;hg>g?7uofW5=Q9tCU@_~E(c*bwus@*t)@6aKj8 z5cl0rcgoo6ipK89tPP6y+NHw2f*`G;)U|Wh?`#YA+sA*=NMH1qVvV(EBcGCcsfuwD z&9SvUW!5vbh_=E%L;zN^g0EJ(X90nnf+n(^8Z>#Pyin7rmh27`=?9xp$SPf_IcTl%2=DtCWLw*d78eUIBFi@6U zg*o~hRkEh=BoZe?PvR-=ke_3o<~9(Eoza23J)OqI26S@2t~MJB^_nk}CxE13I)#i? zd;{o$^(M?Gcl;+{+Y%M0^dFC|eKPn6g|iU0mjPkO>94SWt9U6j+nTnOEiHYI8OZa1 zj7P8By%<`gUZAdt_o0lt8qCyF@D?9@FZ|A=4)VS5nc7;+t8qH5>6`uSLF&0ukaEdx zHgq%-{2wgb(|z_2#&cM%s&5fMs`6V*SxC5#=!z=YGY~V~YrQsoUIgx)2ZqU`E%&~{ zWX;mYz3}6m3ehXin=QRpUnbJzjPwY284u%(rIPoYp`MvP>*5a=^U2KT_7I+>&b~D2 zKR0=)_yOI-gR5v833t0#p&6^lZRI)N)HZiB#nd7H=nHm30Btr0s+Rg@h6x0-!+>t> z&ooEn1{flD>1;vi7|&5b+z19blr>(y|-fD2+tez0iyHreLEw8|b~%$zKwP z{L;%e>lVU5t+n%havcqW$CWy3(kYEElo<*p?)UIQG$6w)Cdd1MUC+EcGhe}VgT|5) zu!lcBobwC~nz&+fHHoR>sEauMVo$*|n8cFod*55Me^H<#Se%hKx?l1zi-rFjI!n{bzcjo1@2>Z-QM#aFcZ9(O_@n&i z*J6Vcr#x3eO;X7V2Qk7q0~i|a#24Nr=EoCZqop`v_-$Q0+Q5&t)ePHuC5J$RSJ0xF zPpnApZ5Q2jH0-|dzUi}f{3^fo=(%;6710|(I9ZcZ&8W6wTd{{K&Qrz2pY!Vy(^y^< z9>qyU4*K-yXKs3OF4?TCgJjAkHbP-y?9rY;G}puelh$y5-f+>Ql$bBNr$W&<5|o|- zk{8gd!#9MX8T$P53y&~uL6V`7%3H0U^x@7noh$0s;le=Tybc#}QVHvJyU#a!Bbur< z(Z53=aV-g0$#nA(FGTw!>9>g>?shyx7y{h0(r|%!onZd=1Izvv8(qvEOTqc01R}B@ zYh$Ah{#lZzUS8cVpMTHo*P;1~qAqKlOEx-*;WWR4Lr@#knr`l_t@_LtecNlBv6*~~ z<|Tag0NQ@Em=?aJpVRtfw61Fgh-Ka%n>lUl@%Lz0oR@QcRRM%gff3S9!jIKHX{Z-& zV0tQGT3w!wYyQ&4H3!QG7iG(*>RaFJ1r)Wx%}$XNOioNQLh=XsD!hpulGNeVflB4V z?XmaR%}HEp78&j>gN#<7`9@8gdA|CujXG|eZ-0HnFQYYlFT9aF)>zTnExMlNuLmAe z5y)?_8qbD6OaIXdk**w_xEm0p2kmAPfu1NB_#H8k6ntvXBvJxf*;v>imJONFI#p{k(sST>F?zD4FZ$^&e%p8G-iCfH! zdi0LgAf_Uzm!mFtAR2~H zZSvQOk%ZTv?*-e&7020R?7a+;b`pb-dWEWAfjJFk7XdbTru7PM`V@Yv5;6~S$I)2U z)51IV+>=ePzOe*S-)%L{fdkrOd!sd_{sAbrR|eZClU^2EqJOW%24{`}V=~=bzz@ET z%!wyIgIAEEDhIg6KTyH>%Z~uQ;vGXqxlP_Bzl8(d(m+M1TVH)wsuO&)lfeecB$6EX zn=tajc+at!P7IR08E>qxQ2U|%Q+c9=V0@~F{MAw-^{vuxi6QxfVxcs3G^lFDg!faJ zifzdc`DR85`qtXd^0p^>{++qXJq#?t@C~$OS6W#vq)1n=i2)&`tfjD82a9yuUG#2( zg>?bXU-(;_xTI4cwxyP&va`NtXgIN}>0NA0S!wIU^t#-)pnsV=ErHRuL@57)T@hO@ zPJPWg-bCN#O@KhN*axw1xuBtgo6iTSR=@H;8<)zRpquSKEtEK4Cz}Ruf6j1A~vKEF{)ggj1;xa1kJCTG$uy@??@gpww5+}lmWtK$tkxSFh`fA-RJkvD ztlq?yF2w4}GuK`!wx%NR);ENXm*odYRHc($MFHRGByfE%5PQe%wp3v^yi@EAPKG83 z;;TOqOCk`PC8(HEo$4eZ%9;lRM9}34ZwLutj99%c$*Ld+98QwC#Alxx+s41s@?{&e z_+Dspi_S9X#)93P7>Yd7O8E9NuF+UdZn`gnxb%L`pSZ#>RqU-u#Q@I$?w&J%Ayhw0 zs97IFsLm{;4I86kqqIZjBtosQGzvkQ)<{T|g|{S!^uW6xiX&|&3f>E=twJCX*2p|x zeUYg^nR%3fQ7m1*Oil(IG4 z#t}j~u{`wv^};99fSmVEOA8`~jD7F)e$&a{W>o8}DHQR&a7Mm&M$k!I$6c1oC#(dS z&8V*A?O>6*g}t%lfE@A|kw0U#>Ck1;a9_TO!1*Z#9Xsa~1k5T7A^LHuioHTH+l6Q) z3k{8j{^VpinrE!tkqt9%QFGh3=i~?Q&OzAmYlFi?jkGxTea}GO@FCFu2=qbm%P?L) zN54>r#rIus1aiJBjTorH^!yK^>RUiM2ql+zkRLdHhZ)271SrR`hlCC(;KnNGXyzl| zf)2g~RcJkgs2LAauxyxjTwz$CYISIX{8q#80!K#xOXidjffH>PYGg1dA;9mkbCUX$ zioE%ZCz3*)lH<3i478PA!_EQtG0b{KhiGmc7h~i!D>>3a82qb#Fb(&J%$|;ek%ovfydH1(^S1 z5t5HXtu|OtCs~hq#T>ADUq`udivmzO!>Nlsk0U29bryz&g=4Zv<89Ai6KXJZ7ES`E z^y*E+l&Tc+Qf`o%I^_%^z|h1#=;F7bJY6CB`L6 ze%*bt_8$4tb?|3agxcZ$9Y%yUhNo~vM(9h1s?ryvaRY&RctP8@uY)B$Xitvw&5E4vUj41)o3Or88R2u7t3)kOW4Z03vR6xixP)cex+bMW30LEfjYW_4R86T24j(jyhRI=Wd^r_<}4Y^T(HFs=27n=1|P8Y(QX1P5>U5}y8(248kSW2 zz%u6SI_`k*$f8Z9�T+3PdPYA^vWzFYyY;E<#2srr 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 z z-a<1esep7S3(7S6v<@*CCWA&$a5tRvNBCm|uy zLhi$Uy+YtG#pwb$y8eNM#lOylF+0`m10M}9mHQV1hJBhtVTJM9(v_$tA=<;fEf}L? zyT~>a3pt?G=F8riSQ`Aap)WOAdJP_eSsB@&HSM7%V3C}8&)gwsN7l|}LQp!dhl}DE z)jbsdm{AmnnMoVVIC3doRkHKTyUn{Js_GB4)Ur1VCPE=XC%2}5rE*!3?qZ}gXF$3QlZ<#@<9&9cNr zLX6Se=f>=I_W>MLWpF5*yn|z1mT(hhIE0O^LdjRW>I;Iets&NkZCsx{s8C5+m=p*w zet9ApJ(qNW03}(-G@5>~n)Bm=AmISQb^LIkPs0>%y&qy4R9yI~N}m#kvqG@ORZvvb zaBT>xStZ}uK-_DJU{KB#cM$_hn%NzeuEJpfB4xMIn5YJ_OK#8o%dL^{%R>;%V%y$_^p>PWX9b0aBbB1ysnV-ej}YhMA(0 zDZrz>S}pQB*Zc@mCD^_YGvJiXfSw4rh$Izntj+~=CL2p$Xc8FIm?Cn^mv~caUB#73 zf)d(cF3E$GMP6)cfg*H7(qIAzFKd!pG0MFGq{jLXFwR78)fdWM4z- zNZh1C6nuVB{s zlEmnT%&m$I8`*2MIP`iXdI*C z%}o6Wb+n1a3Y%5mufT4vQU$OwW1qX4#_05r-7*+x*`6_6pjc6g{8<5#4N~P(vReuZ z60Uz?K_#jyz~NKJFa*^ZahZ4V_H@)F*C@Y?%_tvBC9H&&qm`G9@sJ-txQc3I#<8ow zrXuGfbD^8h`|6qbdG@``N7J!oSV2wI?j@pdm8?G6?lMb z$fb=*cJXNkv!gJw4N(@<&@g@_%dDff)l$_YdTP(Kp(AJ*auawMYI~xN|aL$t!Zsk zMtF`cC{gvdHEK&sY`qZzX3$hYKlVTy0VksNrgd%b(6y*FA17oObA0JfK0y4QdpwWJ;t5$Wm-DJXsxgJo`u_AZy*udZB;a8}4_`0Kozf~aUyG;;Mg)+ha zRi<_kp~NcEBuD0bC6Uts85f8If}fIN-D6!NUpxu~IUT-)li%M7+#>lJJQFQ+N-EOHpXc0F zYDx#KxlxbCRgzZcl#s+jOh^5-l6wAy+%KOi+zu18^4n%+P=9!=6ipEABwtw@W5A1@J3Yu%})4{s?WptQ_yR#zx{dU97uKHhKt4B z7DF_0g)<^09$U;0$XmNO;0;(-w7Wf0vo3_B7r4E^kHs}|gSbF*!LKwn7c{m|dnfOj zU-UeYg1_3{EYO=jX&?IIjoQNR<+rdfC^`@XyA6I{@Iw2-sZN8RrQB>7q5S{A6P@qk+k#nKZ1Myx56Krc>B-U5BmD`UwHv5VU#onQYl%6})de_=mx?AH&i{TP1(H-8N`q^bA!J!|jRSL}z5ef;tK|CY6X-8%f- zdwS#7f2Kd5E%^T^ipK4K4KUKg`)@wL1ONL#{%y$L`M>e{{|X9o`7_UlDD(#zyDpv|MgM(kFRwkzy87B_yaz)T*vtQ zi&6XE{z)acUu`*~kGi*}`Auu@>)*U$3uf0RUnh0Se=nC?x%+qcmo>colfSAf>DM3s zQ+0#!`2Ts-{^lQOd%u42kL&i%KMwt`xcMXab25MO3*_{s`Q+#HI> zj{nEj{$p$ZU&UalXTAG7ga8Nt2%PmSQjmH*}IXo^z)(yuB0@BXqpHa~{T-$q5B sx6AJz1l)1gn)>etKdCi;V93xiu0#1d;ZyCee?{B>gd=JVMvu+^1IUyPbpQYW literal 0 HcmV?d00001 diff --git a/example/network/lwip_iperf/configs/d2000_aarch32_test_lwip_iperf.config b/example/network/lwip_iperf/configs/d2000_aarch32_test_lwip_iperf.config index 545eea42..93f0c1d3 100644 --- a/example/network/lwip_iperf/configs/d2000_aarch32_test_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/d2000_aarch32_test_lwip_iperf.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -544,6 +546,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -553,6 +556,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -575,6 +580,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/d2000_aarch64_test_lwip_iperf.config b/example/network/lwip_iperf/configs/d2000_aarch64_test_lwip_iperf.config index 502738e5..c89e2bbe 100644 --- a/example/network/lwip_iperf/configs/d2000_aarch64_test_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/d2000_aarch64_test_lwip_iperf.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -533,6 +535,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -542,6 +545,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -564,6 +569,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/e2000d_aarch32_demo_lwip_iperf.config b/example/network/lwip_iperf/configs/e2000d_aarch32_demo_lwip_iperf.config index 8d8584b5..5c5515f0 100644 --- a/example/network/lwip_iperf/configs/e2000d_aarch32_demo_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/e2000d_aarch32_demo_lwip_iperf.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -558,6 +560,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -567,6 +570,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -589,6 +594,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/e2000d_aarch64_demo_lwip_iperf.config b/example/network/lwip_iperf/configs/e2000d_aarch64_demo_lwip_iperf.config index 34f1b201..7d72acee 100644 --- a/example/network/lwip_iperf/configs/e2000d_aarch64_demo_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/e2000d_aarch64_demo_lwip_iperf.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -547,6 +549,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -556,6 +559,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -578,6 +583,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/e2000q_aarch32_demo_lwip_iperf.config b/example/network/lwip_iperf/configs/e2000q_aarch32_demo_lwip_iperf.config index a540fd9d..076bf520 100644 --- a/example/network/lwip_iperf/configs/e2000q_aarch32_demo_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/e2000q_aarch32_demo_lwip_iperf.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -557,6 +559,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -566,6 +569,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -588,6 +593,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/e2000q_aarch64_demo_lwip_iperf.config b/example/network/lwip_iperf/configs/e2000q_aarch64_demo_lwip_iperf.config index 23a8058f..d10149fe 100644 --- a/example/network/lwip_iperf/configs/e2000q_aarch64_demo_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/e2000q_aarch64_demo_lwip_iperf.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -546,6 +548,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -555,6 +558,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -577,6 +582,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/ft2004_aarch32_dsk_lwip_iperf.config b/example/network/lwip_iperf/configs/ft2004_aarch32_dsk_lwip_iperf.config index a2079705..1ef37928 100644 --- a/example/network/lwip_iperf/configs/ft2004_aarch32_dsk_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/ft2004_aarch32_dsk_lwip_iperf.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -544,6 +546,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -553,6 +556,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -575,6 +580,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/ft2004_aarch64_dsk_lwip_iperf.config b/example/network/lwip_iperf/configs/ft2004_aarch64_dsk_lwip_iperf.config index 221f6dc9..f7edfe54 100644 --- a/example/network/lwip_iperf/configs/ft2004_aarch64_dsk_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/ft2004_aarch64_dsk_lwip_iperf.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -533,6 +535,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -542,6 +545,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -564,6 +569,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/phytiumpi_aarch32_firefly_lwip_iperf.config b/example/network/lwip_iperf/configs/phytiumpi_aarch32_firefly_lwip_iperf.config index fb47b17c..4f4bc00f 100644 --- a/example/network/lwip_iperf/configs/phytiumpi_aarch32_firefly_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/phytiumpi_aarch32_firefly_lwip_iperf.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -556,6 +558,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -565,6 +568,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -587,6 +592,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/configs/phytiumpi_aarch64_firefly_lwip_iperf.config b/example/network/lwip_iperf/configs/phytiumpi_aarch64_firefly_lwip_iperf.config index c8bdff45..f188359e 100644 --- a/example/network/lwip_iperf/configs/phytiumpi_aarch64_firefly_lwip_iperf.config +++ b/example/network/lwip_iperf/configs/phytiumpi_aarch64_firefly_lwip_iperf.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -545,6 +547,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -554,6 +557,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -576,6 +581,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/sdkconfig b/example/network/lwip_iperf/sdkconfig index c8bdff45..f188359e 100644 --- a/example/network/lwip_iperf/sdkconfig +++ b/example/network/lwip_iperf/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -545,6 +547,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -554,6 +557,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -576,6 +581,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_iperf/sdkconfig.h b/example/network/lwip_iperf/sdkconfig.h index c5170047..b9dde9a7 100644 --- a/example/network/lwip_iperf/sdkconfig.h +++ b/example/network/lwip_iperf/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -477,6 +479,7 @@ #define CONFIG_LWIP_PORT_DHCP_PRIORITY 5 /* end of lwip port thread Configuration */ /* end of LWIP Freertos Port Configuration */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -485,6 +488,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -505,6 +510,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/network/lwip_startup/configs/d2000_aarch32_test_lwip_startup.config b/example/network/lwip_startup/configs/d2000_aarch32_test_lwip_startup.config index 1ff6a289..d58900d6 100644 --- a/example/network/lwip_startup/configs/d2000_aarch32_test_lwip_startup.config +++ b/example/network/lwip_startup/configs/d2000_aarch32_test_lwip_startup.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -544,6 +546,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -553,6 +556,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -575,6 +580,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/d2000_aarch64_test_lwip_startup.config b/example/network/lwip_startup/configs/d2000_aarch64_test_lwip_startup.config index ee31f56e..328002ae 100644 --- a/example/network/lwip_startup/configs/d2000_aarch64_test_lwip_startup.config +++ b/example/network/lwip_startup/configs/d2000_aarch64_test_lwip_startup.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -533,6 +535,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -542,6 +545,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -564,6 +569,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/e2000d_aarch32_demo_lwip_startup.config b/example/network/lwip_startup/configs/e2000d_aarch32_demo_lwip_startup.config index 0d12b462..51be855a 100644 --- a/example/network/lwip_startup/configs/e2000d_aarch32_demo_lwip_startup.config +++ b/example/network/lwip_startup/configs/e2000d_aarch32_demo_lwip_startup.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -557,6 +559,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -566,6 +569,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -588,6 +593,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/e2000d_aarch64_demo_lwip_startup.config b/example/network/lwip_startup/configs/e2000d_aarch64_demo_lwip_startup.config index c68220f6..e86a2802 100644 --- a/example/network/lwip_startup/configs/e2000d_aarch64_demo_lwip_startup.config +++ b/example/network/lwip_startup/configs/e2000d_aarch64_demo_lwip_startup.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -546,6 +548,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -555,6 +558,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -577,6 +582,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/e2000q_aarch32_demo_lwip_startup.config b/example/network/lwip_startup/configs/e2000q_aarch32_demo_lwip_startup.config index d6c04967..f6c67bc7 100644 --- a/example/network/lwip_startup/configs/e2000q_aarch32_demo_lwip_startup.config +++ b/example/network/lwip_startup/configs/e2000q_aarch32_demo_lwip_startup.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -556,6 +558,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -565,6 +568,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -587,6 +592,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/e2000q_aarch64_demo_lwip_startup.config b/example/network/lwip_startup/configs/e2000q_aarch64_demo_lwip_startup.config index 31c14462..95618675 100644 --- a/example/network/lwip_startup/configs/e2000q_aarch64_demo_lwip_startup.config +++ b/example/network/lwip_startup/configs/e2000q_aarch64_demo_lwip_startup.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -545,6 +547,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -554,6 +557,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -576,6 +581,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/ft2004_aarch32_dsk_lwip_startup.config b/example/network/lwip_startup/configs/ft2004_aarch32_dsk_lwip_startup.config index fa7459c2..8966f383 100644 --- a/example/network/lwip_startup/configs/ft2004_aarch32_dsk_lwip_startup.config +++ b/example/network/lwip_startup/configs/ft2004_aarch32_dsk_lwip_startup.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -544,6 +546,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -553,6 +556,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -575,6 +580,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/ft2004_aarch64_dsk_lwip_startup.config b/example/network/lwip_startup/configs/ft2004_aarch64_dsk_lwip_startup.config index 1dab7e68..94a605a6 100644 --- a/example/network/lwip_startup/configs/ft2004_aarch64_dsk_lwip_startup.config +++ b/example/network/lwip_startup/configs/ft2004_aarch64_dsk_lwip_startup.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -533,6 +535,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -542,6 +545,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -564,6 +569,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/phytiumpi_aarch32_firefly_lwip_startup.config b/example/network/lwip_startup/configs/phytiumpi_aarch32_firefly_lwip_startup.config index ef901467..94b25d90 100644 --- a/example/network/lwip_startup/configs/phytiumpi_aarch32_firefly_lwip_startup.config +++ b/example/network/lwip_startup/configs/phytiumpi_aarch32_firefly_lwip_startup.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -555,6 +557,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -564,6 +567,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -586,6 +591,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/configs/phytiumpi_aarch64_firefly_lwip_startup.config b/example/network/lwip_startup/configs/phytiumpi_aarch64_firefly_lwip_startup.config index 146d7810..975c00ef 100644 --- a/example/network/lwip_startup/configs/phytiumpi_aarch64_firefly_lwip_startup.config +++ b/example/network/lwip_startup/configs/phytiumpi_aarch64_firefly_lwip_startup.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -544,6 +546,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -553,6 +556,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -575,6 +580,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/sdkconfig b/example/network/lwip_startup/sdkconfig index 146d7810..975c00ef 100644 --- a/example/network/lwip_startup/sdkconfig +++ b/example/network/lwip_startup/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -544,6 +546,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -553,6 +556,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -575,6 +580,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/lwip_startup/sdkconfig.h b/example/network/lwip_startup/sdkconfig.h index 6388755d..9fe69c98 100644 --- a/example/network/lwip_startup/sdkconfig.h +++ b/example/network/lwip_startup/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -476,6 +478,7 @@ #define CONFIG_LWIP_PORT_DHCP_PRIORITY 5 /* end of lwip port thread Configuration */ /* end of LWIP Freertos Port Configuration */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -484,6 +487,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -504,6 +509,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/network/lwip_startup/src/lwip_dhcp_example.c b/example/network/lwip_startup/src/lwip_dhcp_example.c index 08ae7c3c..81982171 100644 --- a/example/network/lwip_startup/src/lwip_dhcp_example.c +++ b/example/network/lwip_startup/src/lwip_dhcp_example.c @@ -123,16 +123,19 @@ static int DhcpService_Is_Sucess() { struct netif *netif; char * ip_addr; + int ret = 0; for (int i = 0; i < MAC_NUM; i++) { netif = LwipPortGetByName(board_mac_config[i].lwip_mac_config.name); ip_addr = ipaddr_ntoa(&(netif->ip_addr)); if(strcmp(ip_addr,board_mac_config[i].ipaddr) == 0) - return 0; + printf("Eth%d dhcp service failed, please check the network configuration and physical connection status.\r\n", i); + else + ret++; } - - return 1; + + return ret; } void LwipDhcpInitTask(void) diff --git a/example/network/sockets/udp_multicast/configs/d2000_aarch32_test_udp_multicast.config b/example/network/sockets/udp_multicast/configs/d2000_aarch32_test_udp_multicast.config index 2e1d8a04..82f16ce1 100644 --- a/example/network/sockets/udp_multicast/configs/d2000_aarch32_test_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/d2000_aarch32_test_udp_multicast.config @@ -71,6 +71,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -116,6 +117,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -561,6 +563,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -570,6 +573,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -592,6 +597,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/d2000_aarch64_test_udp_multicast.config b/example/network/sockets/udp_multicast/configs/d2000_aarch64_test_udp_multicast.config index 1f17ef76..26363a87 100644 --- a/example/network/sockets/udp_multicast/configs/d2000_aarch64_test_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/d2000_aarch64_test_udp_multicast.config @@ -65,6 +65,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -550,6 +552,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -559,6 +562,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -581,6 +586,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/e2000d_aarch32_demo_udp_multicast.config b/example/network/sockets/udp_multicast/configs/e2000d_aarch32_demo_udp_multicast.config index db76ff72..ea53593d 100644 --- a/example/network/sockets/udp_multicast/configs/e2000d_aarch32_demo_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/e2000d_aarch32_demo_udp_multicast.config @@ -70,6 +70,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -129,6 +130,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -574,6 +576,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -583,6 +586,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -605,6 +610,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/e2000d_aarch64_demo_udp_multicast.config b/example/network/sockets/udp_multicast/configs/e2000d_aarch64_demo_udp_multicast.config index 897ea773..8b6a7103 100644 --- a/example/network/sockets/udp_multicast/configs/e2000d_aarch64_demo_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/e2000d_aarch64_demo_udp_multicast.config @@ -64,6 +64,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -123,6 +124,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -563,6 +565,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -572,6 +575,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -594,6 +599,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/e2000q_aarch32_demo_udp_multicast.config b/example/network/sockets/udp_multicast/configs/e2000q_aarch32_demo_udp_multicast.config index 09d4844c..31b8c17a 100644 --- a/example/network/sockets/udp_multicast/configs/e2000q_aarch32_demo_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/e2000q_aarch32_demo_udp_multicast.config @@ -70,6 +70,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -128,6 +129,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -573,6 +575,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -582,6 +585,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -604,6 +609,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/e2000q_aarch64_demo_udp_multicast.config b/example/network/sockets/udp_multicast/configs/e2000q_aarch64_demo_udp_multicast.config index 2bb4f2be..fc30f047 100644 --- a/example/network/sockets/udp_multicast/configs/e2000q_aarch64_demo_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/e2000q_aarch64_demo_udp_multicast.config @@ -64,6 +64,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -122,6 +123,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -562,6 +564,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -571,6 +574,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -593,6 +598,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/ft2004_aarch32_dsk_udp_multicast.config b/example/network/sockets/udp_multicast/configs/ft2004_aarch32_dsk_udp_multicast.config index f279e572..c0b7e36c 100644 --- a/example/network/sockets/udp_multicast/configs/ft2004_aarch32_dsk_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/ft2004_aarch32_dsk_udp_multicast.config @@ -71,6 +71,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -116,6 +117,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -561,6 +563,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -570,6 +573,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -592,6 +597,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/ft2004_aarch64_dsk_udp_multicast.config b/example/network/sockets/udp_multicast/configs/ft2004_aarch64_dsk_udp_multicast.config index 5b46e1d1..61104ed0 100644 --- a/example/network/sockets/udp_multicast/configs/ft2004_aarch64_dsk_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/ft2004_aarch64_dsk_udp_multicast.config @@ -65,6 +65,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -550,6 +552,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -559,6 +562,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -581,6 +586,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/phytiumpi_aarch32_firefly_udp_multicast.config b/example/network/sockets/udp_multicast/configs/phytiumpi_aarch32_firefly_udp_multicast.config index dc7b2db0..b0e29d24 100644 --- a/example/network/sockets/udp_multicast/configs/phytiumpi_aarch32_firefly_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/phytiumpi_aarch32_firefly_udp_multicast.config @@ -70,6 +70,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -127,6 +128,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -572,6 +574,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -581,6 +584,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -603,6 +608,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/configs/phytiumpi_aarch64_firefly_udp_multicast.config b/example/network/sockets/udp_multicast/configs/phytiumpi_aarch64_firefly_udp_multicast.config index 3e13632e..beb792d9 100644 --- a/example/network/sockets/udp_multicast/configs/phytiumpi_aarch64_firefly_udp_multicast.config +++ b/example/network/sockets/udp_multicast/configs/phytiumpi_aarch64_firefly_udp_multicast.config @@ -64,6 +64,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -121,6 +122,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -561,6 +563,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -570,6 +573,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -592,6 +597,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/sdkconfig b/example/network/sockets/udp_multicast/sdkconfig index 3e13632e..beb792d9 100644 --- a/example/network/sockets/udp_multicast/sdkconfig +++ b/example/network/sockets/udp_multicast/sdkconfig @@ -64,6 +64,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -121,6 +122,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -561,6 +563,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -570,6 +573,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -592,6 +597,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/sockets/udp_multicast/sdkconfig.h b/example/network/sockets/udp_multicast/sdkconfig.h index a0bb68af..8a29ccff 100644 --- a/example/network/sockets/udp_multicast/sdkconfig.h +++ b/example/network/sockets/udp_multicast/sdkconfig.h @@ -58,6 +58,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -110,6 +111,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -490,6 +492,7 @@ #define CONFIG_LWIP_PORT_DHCP_PRIORITY 5 /* end of lwip port thread Configuration */ /* end of LWIP Freertos Port Configuration */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -498,6 +501,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -518,6 +523,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 11 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/network/wlan/configs/e2000d_aarch32_demo_wlan.config b/example/network/wlan/configs/e2000d_aarch32_demo_wlan.config index 67034f48..21c63db5 100644 --- a/example/network/wlan/configs/e2000d_aarch32_demo_wlan.config +++ b/example/network/wlan/configs/e2000d_aarch32_demo_wlan.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -543,6 +545,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -552,6 +555,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -596,6 +601,8 @@ CONFIG_USE_FSL_WIFI=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/wlan/configs/e2000d_aarch64_demo_wlan.config b/example/network/wlan/configs/e2000d_aarch64_demo_wlan.config index 5fa2e47a..c11a209f 100644 --- a/example/network/wlan/configs/e2000d_aarch64_demo_wlan.config +++ b/example/network/wlan/configs/e2000d_aarch64_demo_wlan.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -532,6 +534,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -541,6 +544,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -585,6 +590,8 @@ CONFIG_USE_FSL_WIFI=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/wlan/configs/e2000q_aarch32_demo_wlan.config b/example/network/wlan/configs/e2000q_aarch32_demo_wlan.config index 020343d5..c2f3b74f 100644 --- a/example/network/wlan/configs/e2000q_aarch32_demo_wlan.config +++ b/example/network/wlan/configs/e2000q_aarch32_demo_wlan.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -542,6 +544,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -551,6 +554,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -595,6 +600,8 @@ CONFIG_USE_FSL_WIFI=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/wlan/configs/e2000q_aarch64_demo_wlan.config b/example/network/wlan/configs/e2000q_aarch64_demo_wlan.config index 107182d3..dcad5c88 100644 --- a/example/network/wlan/configs/e2000q_aarch64_demo_wlan.config +++ b/example/network/wlan/configs/e2000q_aarch64_demo_wlan.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -531,6 +533,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -540,6 +543,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -584,6 +589,8 @@ CONFIG_USE_FSL_WIFI=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/wlan/sdkconfig b/example/network/wlan/sdkconfig index 107182d3..dcad5c88 100644 --- a/example/network/wlan/sdkconfig +++ b/example/network/wlan/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -531,6 +533,7 @@ CONFIG_LWIP_PORT_DHCP_PRIORITY=5 # end of lwip port thread Configuration # end of LWIP Freertos Port Configuration +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -540,6 +543,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -584,6 +589,8 @@ CONFIG_USE_FSL_WIFI=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/network/wlan/sdkconfig.h b/example/network/wlan/sdkconfig.h index 5af5f4dc..301ed5e7 100644 --- a/example/network/wlan/sdkconfig.h +++ b/example/network/wlan/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "e2000" #define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 @@ -97,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -465,6 +467,7 @@ #define CONFIG_LWIP_PORT_DHCP_PRIORITY 5 /* end of lwip port thread Configuration */ /* end of LWIP Freertos Port Configuration */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -473,6 +476,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -510,6 +515,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/can/can/configs/d2000_aarch32_test_can.config b/example/peripheral/can/can/configs/d2000_aarch32_test_can.config index af4c7a51..a70c20cf 100644 --- a/example/peripheral/can/can/configs/d2000_aarch32_test_can.config +++ b/example/peripheral/can/can/configs/d2000_aarch32_test_can.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/d2000_aarch64_test_can.config b/example/peripheral/can/can/configs/d2000_aarch64_test_can.config index 727cde34..91401df1 100644 --- a/example/peripheral/can/can/configs/d2000_aarch64_test_can.config +++ b/example/peripheral/can/can/configs/d2000_aarch64_test_can.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -284,6 +286,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -293,6 +296,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -315,6 +320,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/e2000d_aarch32_demo_can.config b/example/peripheral/can/can/configs/e2000d_aarch32_demo_can.config index b1dc27ab..5331dc5b 100644 --- a/example/peripheral/can/can/configs/e2000d_aarch32_demo_can.config +++ b/example/peripheral/can/can/configs/e2000d_aarch32_demo_can.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/e2000d_aarch64_demo_can.config b/example/peripheral/can/can/configs/e2000d_aarch64_demo_can.config index dd1e9859..acd3ac41 100644 --- a/example/peripheral/can/can/configs/e2000d_aarch64_demo_can.config +++ b/example/peripheral/can/can/configs/e2000d_aarch64_demo_can.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,6 +333,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/e2000q_aarch32_demo_can.config b/example/peripheral/can/can/configs/e2000q_aarch32_demo_can.config index 419e9874..2273373c 100644 --- a/example/peripheral/can/can/configs/e2000q_aarch32_demo_can.config +++ b/example/peripheral/can/can/configs/e2000q_aarch32_demo_can.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/e2000q_aarch64_demo_can.config b/example/peripheral/can/can/configs/e2000q_aarch64_demo_can.config index 79a9a100..5069b0c4 100644 --- a/example/peripheral/can/can/configs/e2000q_aarch64_demo_can.config +++ b/example/peripheral/can/can/configs/e2000q_aarch64_demo_can.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/ft2004_aarch32_dsk_can.config b/example/peripheral/can/can/configs/ft2004_aarch32_dsk_can.config index ece63f38..2a65e5e0 100644 --- a/example/peripheral/can/can/configs/ft2004_aarch32_dsk_can.config +++ b/example/peripheral/can/can/configs/ft2004_aarch32_dsk_can.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/configs/ft2004_aarch64_dsk_can.config b/example/peripheral/can/can/configs/ft2004_aarch64_dsk_can.config index 6a2cb559..0c321d86 100644 --- a/example/peripheral/can/can/configs/ft2004_aarch64_dsk_can.config +++ b/example/peripheral/can/can/configs/ft2004_aarch64_dsk_can.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -284,6 +286,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -293,6 +296,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -315,6 +320,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/sdkconfig b/example/peripheral/can/can/sdkconfig index 6a2cb559..0c321d86 100644 --- a/example/peripheral/can/can/sdkconfig +++ b/example/peripheral/can/can/sdkconfig @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -284,6 +286,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -293,6 +296,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -315,6 +320,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/can/sdkconfig.h b/example/peripheral/can/can/sdkconfig.h index 2d422f98..fc817dd3 100644 --- a/example/peripheral/can/can/sdkconfig.h +++ b/example/peripheral/can/can/sdkconfig.h @@ -45,6 +45,7 @@ #define CONFIG_TARGET_FT2004 /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "ft2004" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -86,6 +87,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -251,6 +253,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -259,6 +262,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -279,6 +284,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/can/canfd/configs/e2000d_aarch32_demo_canfd.config b/example/peripheral/can/canfd/configs/e2000d_aarch32_demo_canfd.config index c5090d06..a4da6e9f 100644 --- a/example/peripheral/can/canfd/configs/e2000d_aarch32_demo_canfd.config +++ b/example/peripheral/can/canfd/configs/e2000d_aarch32_demo_canfd.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/canfd/configs/e2000d_aarch64_demo_canfd.config b/example/peripheral/can/canfd/configs/e2000d_aarch64_demo_canfd.config index 7cf83d56..5d309e32 100644 --- a/example/peripheral/can/canfd/configs/e2000d_aarch64_demo_canfd.config +++ b/example/peripheral/can/canfd/configs/e2000d_aarch64_demo_canfd.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,6 +333,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/canfd/configs/e2000q_aarch32_demo_canfd.config b/example/peripheral/can/canfd/configs/e2000q_aarch32_demo_canfd.config index 10f7b5ad..a6a953da 100644 --- a/example/peripheral/can/canfd/configs/e2000q_aarch32_demo_canfd.config +++ b/example/peripheral/can/canfd/configs/e2000q_aarch32_demo_canfd.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/canfd/configs/e2000q_aarch64_demo_canfd.config b/example/peripheral/can/canfd/configs/e2000q_aarch64_demo_canfd.config index b2419bc8..5f8031e0 100644 --- a/example/peripheral/can/canfd/configs/e2000q_aarch64_demo_canfd.config +++ b/example/peripheral/can/canfd/configs/e2000q_aarch64_demo_canfd.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/canfd/sdkconfig b/example/peripheral/can/canfd/sdkconfig index b2419bc8..5f8031e0 100644 --- a/example/peripheral/can/canfd/sdkconfig +++ b/example/peripheral/can/canfd/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_CAN=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/can/canfd/sdkconfig.h b/example/peripheral/can/canfd/sdkconfig.h index 5ad47dbc..022b4deb 100644 --- a/example/peripheral/can/canfd/sdkconfig.h +++ b/example/peripheral/can/canfd/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "e2000" #define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 @@ -97,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -262,6 +264,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -270,6 +273,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -290,6 +295,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/dma/ddma/configs/e2000d_aarch32_demo_ddma.config b/example/peripheral/dma/ddma/configs/e2000d_aarch32_demo_ddma.config index e48b0683..940fa3b0 100644 --- a/example/peripheral/dma/ddma/configs/e2000d_aarch32_demo_ddma.config +++ b/example/peripheral/dma/ddma/configs/e2000d_aarch32_demo_ddma.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -310,6 +312,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -319,6 +322,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -341,6 +346,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/configs/e2000d_aarch64_demo_ddma.config b/example/peripheral/dma/ddma/configs/e2000d_aarch64_demo_ddma.config index 8ad12215..859f8c0f 100644 --- a/example/peripheral/dma/ddma/configs/e2000d_aarch64_demo_ddma.config +++ b/example/peripheral/dma/ddma/configs/e2000d_aarch64_demo_ddma.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -299,6 +301,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -308,6 +311,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -330,6 +335,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/configs/e2000q_aarch32_demo_ddma.config b/example/peripheral/dma/ddma/configs/e2000q_aarch32_demo_ddma.config index cc244d57..a47f29e8 100644 --- a/example/peripheral/dma/ddma/configs/e2000q_aarch32_demo_ddma.config +++ b/example/peripheral/dma/ddma/configs/e2000q_aarch32_demo_ddma.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -309,6 +311,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -318,6 +321,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -340,6 +345,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/configs/e2000q_aarch64_demo_ddma.config b/example/peripheral/dma/ddma/configs/e2000q_aarch64_demo_ddma.config index 17c350cb..66b48125 100644 --- a/example/peripheral/dma/ddma/configs/e2000q_aarch64_demo_ddma.config +++ b/example/peripheral/dma/ddma/configs/e2000q_aarch64_demo_ddma.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -298,6 +300,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -307,6 +310,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -329,6 +334,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/configs/phytiumpi_aarch32_firefly_ddma.config b/example/peripheral/dma/ddma/configs/phytiumpi_aarch32_firefly_ddma.config index 4bf666f8..3b8e4a7a 100644 --- a/example/peripheral/dma/ddma/configs/phytiumpi_aarch32_firefly_ddma.config +++ b/example/peripheral/dma/ddma/configs/phytiumpi_aarch32_firefly_ddma.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/configs/phytiumpi_aarch64_firefly_ddma.config b/example/peripheral/dma/ddma/configs/phytiumpi_aarch64_firefly_ddma.config index 844c1b19..5d1d15a3 100644 --- a/example/peripheral/dma/ddma/configs/phytiumpi_aarch64_firefly_ddma.config +++ b/example/peripheral/dma/ddma/configs/phytiumpi_aarch64_firefly_ddma.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,6 +333,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/sdkconfig b/example/peripheral/dma/ddma/sdkconfig index 844c1b19..5d1d15a3 100644 --- a/example/peripheral/dma/ddma/sdkconfig +++ b/example/peripheral/dma/ddma/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_FDDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,6 +333,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/ddma/sdkconfig.h b/example/peripheral/dma/ddma/sdkconfig.h index 47add5b6..ab296493 100644 --- a/example/peripheral/dma/ddma/sdkconfig.h +++ b/example/peripheral/dma/ddma/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -263,6 +265,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -271,6 +274,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -291,6 +296,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/dma/gdma/configs/e2000d_aarch32_demo_gdma.config b/example/peripheral/dma/gdma/configs/e2000d_aarch32_demo_gdma.config index bf04a4c2..667b0b35 100644 --- a/example/peripheral/dma/gdma/configs/e2000d_aarch32_demo_gdma.config +++ b/example/peripheral/dma/gdma/configs/e2000d_aarch32_demo_gdma.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -309,6 +311,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -318,6 +321,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -340,6 +345,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/configs/e2000d_aarch64_demo_gdma.config b/example/peripheral/dma/gdma/configs/e2000d_aarch64_demo_gdma.config index 5528beec..46e36e85 100644 --- a/example/peripheral/dma/gdma/configs/e2000d_aarch64_demo_gdma.config +++ b/example/peripheral/dma/gdma/configs/e2000d_aarch64_demo_gdma.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -298,6 +300,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -307,6 +310,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -329,6 +334,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/configs/e2000q_aarch32_demo_gdma.config b/example/peripheral/dma/gdma/configs/e2000q_aarch32_demo_gdma.config index 2cbc9b72..fa6b65ae 100644 --- a/example/peripheral/dma/gdma/configs/e2000q_aarch32_demo_gdma.config +++ b/example/peripheral/dma/gdma/configs/e2000q_aarch32_demo_gdma.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/configs/e2000q_aarch64_demo_gdma.config b/example/peripheral/dma/gdma/configs/e2000q_aarch64_demo_gdma.config index 1274d885..8e171576 100644 --- a/example/peripheral/dma/gdma/configs/e2000q_aarch64_demo_gdma.config +++ b/example/peripheral/dma/gdma/configs/e2000q_aarch64_demo_gdma.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,6 +333,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/configs/phytiumpi_aarch32_firefly_gdma.config b/example/peripheral/dma/gdma/configs/phytiumpi_aarch32_firefly_gdma.config index 2251b569..a28bbece 100644 --- a/example/peripheral/dma/gdma/configs/phytiumpi_aarch32_firefly_gdma.config +++ b/example/peripheral/dma/gdma/configs/phytiumpi_aarch32_firefly_gdma.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/configs/phytiumpi_aarch64_firefly_gdma.config b/example/peripheral/dma/gdma/configs/phytiumpi_aarch64_firefly_gdma.config index a4078fe3..f4c6059e 100644 --- a/example/peripheral/dma/gdma/configs/phytiumpi_aarch64_firefly_gdma.config +++ b/example/peripheral/dma/gdma/configs/phytiumpi_aarch64_firefly_gdma.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/sdkconfig b/example/peripheral/dma/gdma/sdkconfig index a4078fe3..f4c6059e 100644 --- a/example/peripheral/dma/gdma/sdkconfig +++ b/example/peripheral/dma/gdma/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_FGDMA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/dma/gdma/sdkconfig.h b/example/peripheral/dma/gdma/sdkconfig.h index 48c4a06b..d19ba9d0 100644 --- a/example/peripheral/dma/gdma/sdkconfig.h +++ b/example/peripheral/dma/gdma/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -262,6 +264,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -270,6 +273,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -290,6 +295,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/gpio/configs/d2000_aarch32_test_gpio.config b/example/peripheral/gpio/configs/d2000_aarch32_test_gpio.config index acf4fd38..e7ae3c0a 100644 --- a/example/peripheral/gpio/configs/d2000_aarch32_test_gpio.config +++ b/example/peripheral/gpio/configs/d2000_aarch32_test_gpio.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/d2000_aarch64_test_gpio.config b/example/peripheral/gpio/configs/d2000_aarch64_test_gpio.config index 4a79bd42..3115ec78 100644 --- a/example/peripheral/gpio/configs/d2000_aarch64_test_gpio.config +++ b/example/peripheral/gpio/configs/d2000_aarch64_test_gpio.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -284,6 +286,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -293,6 +296,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -315,6 +320,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/e2000d_aarch32_demo_gpio.config b/example/peripheral/gpio/configs/e2000d_aarch32_demo_gpio.config index 90b6325c..6be8f2b7 100644 --- a/example/peripheral/gpio/configs/e2000d_aarch32_demo_gpio.config +++ b/example/peripheral/gpio/configs/e2000d_aarch32_demo_gpio.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/e2000d_aarch64_demo_gpio.config b/example/peripheral/gpio/configs/e2000d_aarch64_demo_gpio.config index 2a6e0de4..9c1947c3 100644 --- a/example/peripheral/gpio/configs/e2000d_aarch64_demo_gpio.config +++ b/example/peripheral/gpio/configs/e2000d_aarch64_demo_gpio.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -328,6 +333,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/e2000q_aarch32_demo_gpio.config b/example/peripheral/gpio/configs/e2000q_aarch32_demo_gpio.config index 2907ec3e..f9b162ef 100644 --- a/example/peripheral/gpio/configs/e2000q_aarch32_demo_gpio.config +++ b/example/peripheral/gpio/configs/e2000q_aarch32_demo_gpio.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/e2000q_aarch64_demo_gpio.config b/example/peripheral/gpio/configs/e2000q_aarch64_demo_gpio.config index e44db224..4d2b9592 100644 --- a/example/peripheral/gpio/configs/e2000q_aarch64_demo_gpio.config +++ b/example/peripheral/gpio/configs/e2000q_aarch64_demo_gpio.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/phytiumpi_aarch32_firefly_gpio.config b/example/peripheral/gpio/configs/phytiumpi_aarch32_firefly_gpio.config index 2672e501..9c030ad6 100644 --- a/example/peripheral/gpio/configs/phytiumpi_aarch32_firefly_gpio.config +++ b/example/peripheral/gpio/configs/phytiumpi_aarch32_firefly_gpio.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/configs/phytiumpi_aarch64_firefly_gpio.config b/example/peripheral/gpio/configs/phytiumpi_aarch64_firefly_gpio.config index 0ef8fb65..5b2c32b8 100644 --- a/example/peripheral/gpio/configs/phytiumpi_aarch64_firefly_gpio.config +++ b/example/peripheral/gpio/configs/phytiumpi_aarch64_firefly_gpio.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/sdkconfig b/example/peripheral/gpio/sdkconfig index 0ef8fb65..5b2c32b8 100644 --- a/example/peripheral/gpio/sdkconfig +++ b/example/peripheral/gpio/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/gpio/sdkconfig.h b/example/peripheral/gpio/sdkconfig.h index 7215c87e..36a03a19 100644 --- a/example/peripheral/gpio/sdkconfig.h +++ b/example/peripheral/gpio/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -261,6 +263,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -269,6 +272,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -289,6 +294,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/i2c/configs/e2000d_aarch32_demo_i2c.config b/example/peripheral/i2c/configs/e2000d_aarch32_demo_i2c.config index 7fc449b0..6716f4ba 100644 --- a/example/peripheral/i2c/configs/e2000d_aarch32_demo_i2c.config +++ b/example/peripheral/i2c/configs/e2000d_aarch32_demo_i2c.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -315,6 +317,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -324,6 +327,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -346,6 +351,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/configs/e2000d_aarch64_demo_i2c.config b/example/peripheral/i2c/configs/e2000d_aarch64_demo_i2c.config index 60d9b26e..a92bfaff 100644 --- a/example/peripheral/i2c/configs/e2000d_aarch64_demo_i2c.config +++ b/example/peripheral/i2c/configs/e2000d_aarch64_demo_i2c.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -304,6 +306,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -313,6 +316,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -335,6 +340,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/configs/e2000q_aarch32_demo_i2c.config b/example/peripheral/i2c/configs/e2000q_aarch32_demo_i2c.config index 2d3a0947..798ba498 100644 --- a/example/peripheral/i2c/configs/e2000q_aarch32_demo_i2c.config +++ b/example/peripheral/i2c/configs/e2000q_aarch32_demo_i2c.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/configs/e2000q_aarch64_demo_i2c.config b/example/peripheral/i2c/configs/e2000q_aarch64_demo_i2c.config index 3a83ef6f..073c5980 100644 --- a/example/peripheral/i2c/configs/e2000q_aarch64_demo_i2c.config +++ b/example/peripheral/i2c/configs/e2000q_aarch64_demo_i2c.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/configs/phytiumpi_aarch32_firefly_i2c.config b/example/peripheral/i2c/configs/phytiumpi_aarch32_firefly_i2c.config index 1d22c969..497363e8 100644 --- a/example/peripheral/i2c/configs/phytiumpi_aarch32_firefly_i2c.config +++ b/example/peripheral/i2c/configs/phytiumpi_aarch32_firefly_i2c.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/configs/phytiumpi_aarch64_firefly_i2c.config b/example/peripheral/i2c/configs/phytiumpi_aarch64_firefly_i2c.config index 5b884636..7a24c3db 100644 --- a/example/peripheral/i2c/configs/phytiumpi_aarch64_firefly_i2c.config +++ b/example/peripheral/i2c/configs/phytiumpi_aarch64_firefly_i2c.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/sdkconfig b/example/peripheral/i2c/sdkconfig index 5b884636..7a24c3db 100644 --- a/example/peripheral/i2c/sdkconfig +++ b/example/peripheral/i2c/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_MIO=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2c/sdkconfig.h b/example/peripheral/i2c/sdkconfig.h index 4f87f88b..778c6808 100644 --- a/example/peripheral/i2c/sdkconfig.h +++ b/example/peripheral/i2c/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -266,6 +268,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -274,6 +277,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -294,6 +299,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/i2s/configs/e2000d_aarch32_demo_i2s.config b/example/peripheral/i2s/configs/e2000d_aarch32_demo_i2s.config index 0eac5c9a..3f95cb89 100644 --- a/example/peripheral/i2s/configs/e2000d_aarch32_demo_i2s.config +++ b/example/peripheral/i2s/configs/e2000d_aarch32_demo_i2s.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_NONE=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -325,6 +327,7 @@ CONFIG_FREERTOS_USE_I2S=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -334,6 +337,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -356,6 +361,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2s/configs/e2000d_aarch64_demo_i2s.config b/example/peripheral/i2s/configs/e2000d_aarch64_demo_i2s.config index b7e52842..9b17418e 100644 --- a/example/peripheral/i2s/configs/e2000d_aarch64_demo_i2s.config +++ b/example/peripheral/i2s/configs/e2000d_aarch64_demo_i2s.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_NONE=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_I2S=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2s/configs/e2000q_aarch32_demo_i2s.config b/example/peripheral/i2s/configs/e2000q_aarch32_demo_i2s.config index 836d9de3..d8d1a88f 100644 --- a/example/peripheral/i2s/configs/e2000q_aarch32_demo_i2s.config +++ b/example/peripheral/i2s/configs/e2000q_aarch32_demo_i2s.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_NONE=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -324,6 +326,7 @@ CONFIG_FREERTOS_USE_I2S=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -333,6 +336,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -355,6 +360,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2s/configs/e2000q_aarch64_demo_i2s.config b/example/peripheral/i2s/configs/e2000q_aarch64_demo_i2s.config index 5fb12bb7..34b56874 100644 --- a/example/peripheral/i2s/configs/e2000q_aarch64_demo_i2s.config +++ b/example/peripheral/i2s/configs/e2000q_aarch64_demo_i2s.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_NONE=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_I2S=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2s/sdkconfig b/example/peripheral/i2s/sdkconfig index 5fb12bb7..34b56874 100644 --- a/example/peripheral/i2s/sdkconfig +++ b/example/peripheral/i2s/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_NONE=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_I2S=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/i2s/sdkconfig.h b/example/peripheral/i2s/sdkconfig.h index 65954833..d4b5f496 100644 --- a/example/peripheral/i2s/sdkconfig.h +++ b/example/peripheral/i2s/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "e2000" #define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 @@ -97,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -275,6 +277,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -283,6 +286,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -303,6 +308,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/media/lvgl_demo/configs/e2000d_aarch32_demo_media.config b/example/peripheral/media/lvgl_demo/configs/e2000d_aarch32_demo_media.config index 70536d72..389b715a 100644 --- a/example/peripheral/media/lvgl_demo/configs/e2000d_aarch32_demo_media.config +++ b/example/peripheral/media/lvgl_demo/configs/e2000d_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +119,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -147,13 +155,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/configs/e2000d_aarch64_demo_media.config b/example/peripheral/media/lvgl_demo/configs/e2000d_aarch64_demo_media.config index a81d3100..c3a1f3af 100644 --- a/example/peripheral/media/lvgl_demo/configs/e2000d_aarch64_demo_media.config +++ b/example/peripheral/media/lvgl_demo/configs/e2000d_aarch64_demo_media.config @@ -33,6 +33,12 @@ CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +113,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -141,13 +149,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/configs/e2000q_aarch32_demo_media.config b/example/peripheral/media/lvgl_demo/configs/e2000q_aarch32_demo_media.config index 7f6e8863..31fa0ce9 100644 --- a/example/peripheral/media/lvgl_demo/configs/e2000q_aarch32_demo_media.config +++ b/example/peripheral/media/lvgl_demo/configs/e2000q_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +118,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -146,13 +154,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/configs/e2000q_aarch64_demo_media.config b/example/peripheral/media/lvgl_demo/configs/e2000q_aarch64_demo_media.config index 24f02f8d..6dd80f15 100644 --- a/example/peripheral/media/lvgl_demo/configs/e2000q_aarch64_demo_media.config +++ b/example/peripheral/media/lvgl_demo/configs/e2000q_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +112,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -140,13 +148,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch32_firefly_media.config b/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch32_firefly_media.config index 844e4d6a..13dfcac3 100644 --- a/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch32_firefly_media.config +++ b/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch32_firefly_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +117,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -145,13 +153,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -343,6 +348,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch64_firefly_media.config b/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch64_firefly_media.config index 7342ecf5..08dba790 100644 --- a/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch64_firefly_media.config +++ b/example/peripheral/media/lvgl_demo/configs/phytiumpi_aarch64_firefly_media.config @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +111,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -139,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/sdkconfig b/example/peripheral/media/lvgl_demo/sdkconfig index 3bba792e..b8030431 100644 --- a/example/peripheral/media/lvgl_demo/sdkconfig +++ b/example/peripheral/media/lvgl_demo/sdkconfig @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -141,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -202,7 +202,7 @@ CONFIG_USE_COMPILE_CHAIN=y CONFIG_DEFAULT_LINKER_SCRIPT=y # CONFIG_USER_DEFINED_LD is not set CONFIG_IMAGE_LOAD_ADDRESS=0x80100000 -CONFIG_IMAGE_MAX_LENGTH=0x1000000 +CONFIG_IMAGE_MAX_LENGTH=0x4000000 CONFIG_HEAP_SIZE=1 CONFIG_STACK_SIZE=0x400 # end of Linker Options @@ -303,7 +303,20 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set -# CONFIG_USE_LETTER_SHELL is not set +# CONFIG_USE_MBEDTLS is not set +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + # CONFIG_USE_AMP is not set # CONFIG_USE_YMODEM is not set # CONFIG_USE_SFUD is not set @@ -324,6 +337,8 @@ CONFIG_USE_LVGL=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_demo/sdkconfig.h b/example/peripheral/media/lvgl_demo/sdkconfig.h index 641ae46c..1fa21481 100644 --- a/example/peripheral/media/lvgl_demo/sdkconfig.h +++ b/example/peripheral/media/lvgl_demo/sdkconfig.h @@ -31,6 +31,11 @@ /* CONFIG_BOOT_WITH_FLUSH_CACHE is not set */ /* CONFIG_MMU_DEBUG_PRINTS is not set */ /* end of Arm architecture configuration */ + +/* multi-core system deployment framework */ + +/* CONFIG_USE_MSDF is not set */ +/* end of multi-core system deployment framework */ #define CONFIG_MMU_PAGE_SIZE 0x1000 #define CONFIG_MAX_XLAT_TABLES 256 /* end of Arch configuration */ @@ -130,11 +135,7 @@ /* CONFIG_USE_PWM is not set */ /* CONFIG_USE_IPC is not set */ #define CONFIG_USE_MEDIA - -/* Media Configuration */ - -#define CONFIG_ENABLE_FDC_DP_USE_LIB -/* end of Media Configuration */ +#define CONFIG_USE_FMEDIA /* CONFIG_USE_SCMI_MHU is not set */ /* CONFIG_USE_I2S is not set */ /* CONFIG_USE_I3C is not set */ @@ -183,7 +184,7 @@ #define CONFIG_DEFAULT_LINKER_SCRIPT /* CONFIG_USER_DEFINED_LD is not set */ #define CONFIG_IMAGE_LOAD_ADDRESS 0x80100000 -#define CONFIG_IMAGE_MAX_LENGTH 0x1000000 +#define CONFIG_IMAGE_MAX_LENGTH 0x4000000 #define CONFIG_HEAP_SIZE 1 #define CONFIG_STACK_SIZE 0x400 /* end of Linker Options */ @@ -267,7 +268,18 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ -/* CONFIG_USE_LETTER_SHELL is not set */ +/* CONFIG_USE_MBEDTLS is not set */ +#define CONFIG_USE_LETTER_SHELL + +/* Letter Shell Configuration */ + +#define CONFIG_LS_PL011_UART +#define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ +/* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ /* CONFIG_USE_SFUD is not set */ @@ -287,6 +299,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/media/lvgl_demo/src/cmd.c b/example/peripheral/media/lvgl_demo/src/cmd.c index 34264da1..3305ae8b 100644 --- a/example/peripheral/media/lvgl_demo/src/cmd.c +++ b/example/peripheral/media/lvgl_demo/src/cmd.c @@ -32,7 +32,7 @@ #include "shell_port.h" #include "lv_demo_create.h" - +#include "lv_demo_test.h" static void FFreeRTOSMediaCmdUsage(void) { printf("Usage:\r\n"); diff --git a/example/peripheral/media/lvgl_demo/src/lv_demo_test.c b/example/peripheral/media/lvgl_demo/src/lv_demo_test.c index 8ec76ed9..42643848 100644 --- a/example/peripheral/media/lvgl_demo/src/lv_demo_test.c +++ b/example/peripheral/media/lvgl_demo/src/lv_demo_test.c @@ -40,9 +40,33 @@ #include "fdp.h" #include "fdp_hw.h" #include "fdc_hw.h" +#include "fdcdp_reg.h" +#include "fdcdp_crtc.h" #include "lv_conf.h" #include "lv_port_disp.h" +typedef struct +{ + u32 bit_depth; + u32 bpc; + u32 color_depth; + u32 clock_mode; + u32 color_rep; + u32 width; + u32 height; + u32 multi_mode; +} FuserCfg; + +static const FuserCfg user_cfg = { + .bit_depth = 8, + .bpc = 8, + .color_depth = 32, + .clock_mode = 1, + .color_rep = 0, + .width = 800, + .height = 600, + .multi_mode = 0/*0:clone, 1 :horz, 2:vert*/ +}; /************************** Variable Definitions *****************************/ #define FMEDIA_EVT_INTR(index) BIT(index) #define FMEDIA_CHANNEL_0 0 @@ -96,9 +120,9 @@ static void FFreeRTOSMediaHpdConnectCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); - instance_p->connect_flg[index] = 1; + instance_p->is_initialized[index] = FDCDP_IS_INITIALIZED; printf("Dp:%d connect\r\n", index); } @@ -114,8 +138,8 @@ static void FFreeRTOSMediaHpdBreakCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ - instance_p->connect_flg[index] = 0; + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ + instance_p->is_initialized[index] = FDCDP_NOT_INITIALIZED; FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); printf("Dp:%d disconnect\r\n", index); } @@ -131,7 +155,7 @@ static void FFreeRTOSMediaAuxTimeoutCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect timeout\r\n", index); } @@ -146,7 +170,7 @@ static void FFreeRTOSMediaAuxErrorCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect error\r\n", index); } @@ -161,8 +185,6 @@ static void FFreeRTOSMediaIrqSet(FDcDp *instance_p) FASSERT(instance_p != NULL); u32 cpu_id; u32 index; - FMediaIntrConfig intr_config; - memset(&intr_config, 0, sizeof(intr_config)); GetCpuId(&cpu_id); InterruptSetTargetCpus(instance_p->dp_instance_p[0].config.irq_num, cpu_id);/*the dc0 and dc1 have the same num of irq_num*/ @@ -217,18 +239,36 @@ void FFreeRTOSMediaDeviceInit(void) start_index = channel; end_index = channel + 1; } + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (index = start_index; index < end_index; index ++) { - os_media.dcdp_ctrl.user_config[index].width = 800; - os_media.dcdp_ctrl.user_config[index].height = 600; - os_media.dcdp_ctrl.user_config[index].refresh_rate = 60; - os_media.dcdp_ctrl.user_config[index].color_depth = 32; - os_media.dcdp_ctrl.user_config[index].multi_mode = 0; - os_media.dcdp_ctrl.user_config[index].fb_phy = (uintptr)static_frame_buffer_address; - os_media.dcdp_ctrl.user_config[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + FDcDpCfgInitialize(&os_media.dcdp_ctrl,index); + + os_media.dcdp_ctrl.dc_instance_p[index].config = *FDcLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].config = *FDpLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.bit_depth = user_cfg.bit_depth; + + os_media.dcdp_ctrl.dc_instance_p[index].crtc.bpc = user_cfg.bpc; + + os_media.dcdp_ctrl.dc_instance_p[index].color_depth = user_cfg.color_depth; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.clock_mode = user_cfg.clock_mode; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.color_rep_format = user_cfg.color_rep; + + os_media.dcdp_ctrl.dc_instance_p[index].channel = index; + + os_media.dcdp_ctrl.dc_instance_p[index].fb_addr = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + os_media.dcdp_ctrl.dc_instance_p[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + FDcDpGeneralCfgInitial(&os_media.dcdp_ctrl, index); } - FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(channel, &os_media); - FASSERT_MSG(NULL == media_event, "Event group exists."); + + FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(&os_media,user_cfg.width, user_cfg.height); + FASSERT_MSG(NULL == media_event, "Event group exists."); FASSERT_MSG((media_event = xEventGroupCreate()) != NULL, "Create event group failed."); FFreeRTOSMediaIrqSet(&os_config->dcdp_ctrl); FFreeRTOSMediaIrqAllEnable(&os_config->dcdp_ctrl); @@ -259,24 +299,26 @@ void FFreeRTOSMediaChannelDeinit(u32 id) void FFreeRTOSMediaHpdHandle(void) { u32 index; - u32 ret = FMEDIA_DP_SUCCESS; + u32 ret = FDP_SUCCESS; FFreeRTOSMediaWaitEvent(FMEDIA_EVT_INTR(FMEDIA_CHANNEL_0) | FMEDIA_EVT_INTR(FMEDIA_CHANNEL_1), portMAX_DELAY); - + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (;;) { for (index = 0; index < FDCDP_INSTANCE_NUM; index++) { - if (os_media.dcdp_ctrl.connect_flg[index] == 1) + if (os_media.dcdp_ctrl.is_initialized[index] == FDCDP_NOT_INITIALIZED) { - ret = FDcDpHotPlugConnect(&os_media.dcdp_ctrl, index); + FDcDpCfgInitialize(&os_media.dcdp_ctrl, index); + ret = FDcDpInitial(&os_media.dcdp_ctrl, index, user_cfg.width, user_cfg.height); FFreeRTOSMediaClearEvent(media_event, FMEDIA_EVT_INTR(index)); - if (ret == FMEDIA_DP_SUCCESS) + if (ret == FDP_SUCCESS) { - printf("Hpd task finish , reinit the dp success.\r\n"); + printf("Hpd task finish , reinit the dp success.\r\n"); } - os_media.dcdp_ctrl.connect_flg[index] == 0; + os_media.dcdp_ctrl.is_initialized[index] = FDCDP_IS_INITIALIZED; } + } vTaskDelay(200); } diff --git a/example/peripheral/media/lvgl_indev/configs/e2000d_aarch32_demo_media.config b/example/peripheral/media/lvgl_indev/configs/e2000d_aarch32_demo_media.config index b67648ed..f4eb97da 100644 --- a/example/peripheral/media/lvgl_indev/configs/e2000d_aarch32_demo_media.config +++ b/example/peripheral/media/lvgl_indev/configs/e2000d_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +119,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -147,13 +155,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -359,6 +364,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/configs/e2000d_aarch64_demo_media.config b/example/peripheral/media/lvgl_indev/configs/e2000d_aarch64_demo_media.config index 16568bd4..6e4562ee 100644 --- a/example/peripheral/media/lvgl_indev/configs/e2000d_aarch64_demo_media.config +++ b/example/peripheral/media/lvgl_indev/configs/e2000d_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +113,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -141,13 +149,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -348,6 +353,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/configs/e2000q_aarch32_demo_media.config b/example/peripheral/media/lvgl_indev/configs/e2000q_aarch32_demo_media.config index e9631911..ea7dec49 100644 --- a/example/peripheral/media/lvgl_indev/configs/e2000q_aarch32_demo_media.config +++ b/example/peripheral/media/lvgl_indev/configs/e2000q_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +118,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -146,13 +154,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -358,6 +363,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/configs/e2000q_aarch64_demo_media.config b/example/peripheral/media/lvgl_indev/configs/e2000q_aarch64_demo_media.config index f890f118..0e8fb8e0 100644 --- a/example/peripheral/media/lvgl_indev/configs/e2000q_aarch64_demo_media.config +++ b/example/peripheral/media/lvgl_indev/configs/e2000q_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +112,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -140,13 +148,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -347,6 +352,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch32_firefly_media.config b/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch32_firefly_media.config index c763dc6d..258936e3 100644 --- a/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch32_firefly_media.config +++ b/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch32_firefly_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +117,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -145,13 +153,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -357,6 +362,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch64_firefly_media.config b/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch64_firefly_media.config index 0844bbec..41d72167 100644 --- a/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch64_firefly_media.config +++ b/example/peripheral/media/lvgl_indev/configs/phytiumpi_aarch64_firefly_media.config @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +111,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -139,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -346,6 +351,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/sdkconfig b/example/peripheral/media/lvgl_indev/sdkconfig index 6c6e79c1..41d72167 100644 --- a/example/peripheral/media/lvgl_indev/sdkconfig +++ b/example/peripheral/media/lvgl_indev/sdkconfig @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -141,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -303,7 +303,20 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set -# CONFIG_USE_LETTER_SHELL is not set +# CONFIG_USE_MBEDTLS is not set +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + # CONFIG_USE_AMP is not set # CONFIG_USE_YMODEM is not set # CONFIG_USE_SFUD is not set @@ -338,6 +351,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_indev/sdkconfig.h b/example/peripheral/media/lvgl_indev/sdkconfig.h index 45ed91c2..f869c42d 100644 --- a/example/peripheral/media/lvgl_indev/sdkconfig.h +++ b/example/peripheral/media/lvgl_indev/sdkconfig.h @@ -31,6 +31,11 @@ /* CONFIG_BOOT_WITH_FLUSH_CACHE is not set */ /* CONFIG_MMU_DEBUG_PRINTS is not set */ /* end of Arm architecture configuration */ + +/* multi-core system deployment framework */ + +/* CONFIG_USE_MSDF is not set */ +/* end of multi-core system deployment framework */ #define CONFIG_MMU_PAGE_SIZE 0x1000 #define CONFIG_MAX_XLAT_TABLES 256 /* end of Arch configuration */ @@ -130,11 +135,7 @@ /* CONFIG_USE_PWM is not set */ /* CONFIG_USE_IPC is not set */ #define CONFIG_USE_MEDIA - -/* Media Configuration */ - -#define CONFIG_ENABLE_FDC_DP_USE_LIB -/* end of Media Configuration */ +#define CONFIG_USE_FMEDIA /* CONFIG_USE_SCMI_MHU is not set */ /* CONFIG_USE_I2S is not set */ /* CONFIG_USE_I3C is not set */ @@ -267,7 +268,18 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ -/* CONFIG_USE_LETTER_SHELL is not set */ +/* CONFIG_USE_MBEDTLS is not set */ +#define CONFIG_USE_LETTER_SHELL + +/* Letter Shell Configuration */ + +#define CONFIG_LS_PL011_UART +#define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ +/* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ /* CONFIG_USE_SFUD is not set */ @@ -299,6 +311,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/media/lvgl_indev/src/cmd.c b/example/peripheral/media/lvgl_indev/src/cmd.c index 2b90e87e..752836c4 100644 --- a/example/peripheral/media/lvgl_indev/src/cmd.c +++ b/example/peripheral/media/lvgl_indev/src/cmd.c @@ -31,7 +31,6 @@ #include "shell.h" #include "shell_port.h" -#include "fdc_common_hw.h" #include "fdcdp.h" #include "fdp_hw.h" diff --git a/example/peripheral/media/lvgl_indev/src/lv_indev_test.c b/example/peripheral/media/lvgl_indev/src/lv_indev_test.c index 30c8f713..4ba53c49 100644 --- a/example/peripheral/media/lvgl_indev/src/lv_indev_test.c +++ b/example/peripheral/media/lvgl_indev/src/lv_indev_test.c @@ -38,10 +38,33 @@ #include "fdp_hw.h" #include "fdc_hw.h" #include "fmedia_os.h" - +#include "fdcdp_reg.h" +#include "fdcdp_crtc.h" #include "lv_indev_port.h" #include "lv_port_disp.h" +typedef struct +{ + u32 bit_depth; + u32 bpc; + u32 color_depth; + u32 clock_mode; + u32 color_rep; + u32 width; + u32 height; + u32 multi_mode; +} FuserCfg; + +static const FuserCfg user_cfg = { + .bit_depth = 8, + .bpc = 8, + .color_depth = 32, + .clock_mode = 1, + .color_rep = 0, + .width = 800, + .height = 600, + .multi_mode = 0/*0:clone, 1 :horz, 2:vert*/ +}; /************************** Variable Definitions *****************************/ #define FMEDIA_EVT_INTR(index) BIT(index) #define FMEDIA_CHANNEL_0 0 @@ -97,9 +120,9 @@ static void FFreeRTOSMediaHpdConnectCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); - instance_p->connect_flg[index] = 1; + instance_p->is_initialized[index] = FDCDP_IS_INITIALIZED; printf("Dp:%d connect\r\n", index); } @@ -115,8 +138,8 @@ static void FFreeRTOSMediaHpdBreakCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ - instance_p->connect_flg[index] = 0; + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ + instance_p->is_initialized[index] = FDCDP_NOT_INITIALIZED; FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); printf("Dp:%d disconnect\r\n", index); } @@ -132,7 +155,7 @@ static void FFreeRTOSMediaAuxTimeoutCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect timeout\r\n", index); } @@ -147,7 +170,7 @@ static void FFreeRTOSMediaAuxErrorCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect error\r\n", index); } @@ -162,8 +185,6 @@ static void FFreeRTOSMediaIrqSet(FDcDp *instance_p) FASSERT(instance_p != NULL); u32 cpu_id; u32 index; - FMediaIntrConfig intr_config; - memset(&intr_config, 0, sizeof(intr_config)); GetCpuId(&cpu_id); InterruptSetTargetCpus(instance_p->dp_instance_p[0].config.irq_num, cpu_id);/*the dc0 and dc1 have the same num of irq_num*/ @@ -218,17 +239,34 @@ void FFreeRTOSMediaDeviceInit(void) start_index = channel; end_index = channel + 1; } + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (index = start_index; index < end_index; index ++) { - os_media.dcdp_ctrl.user_config[index].width = 800; - os_media.dcdp_ctrl.user_config[index].height = 600; - os_media.dcdp_ctrl.user_config[index].refresh_rate = 60; - os_media.dcdp_ctrl.user_config[index].color_depth = 32; - os_media.dcdp_ctrl.user_config[index].multi_mode = 0; - os_media.dcdp_ctrl.user_config[index].fb_phy = (uintptr)static_frame_buffer_address; - os_media.dcdp_ctrl.user_config[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + FDcDpCfgInitialize(&os_media.dcdp_ctrl,index); + + os_media.dcdp_ctrl.dc_instance_p[index].config = *FDcLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].config = *FDpLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.bit_depth = user_cfg.bit_depth; + + os_media.dcdp_ctrl.dc_instance_p[index].crtc.bpc = user_cfg.bpc; + + os_media.dcdp_ctrl.dc_instance_p[index].color_depth = user_cfg.color_depth; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.clock_mode = user_cfg.clock_mode; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.color_rep_format = user_cfg.color_rep; + + os_media.dcdp_ctrl.dc_instance_p[index].channel = index; + + os_media.dcdp_ctrl.dc_instance_p[index].fb_addr = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + os_media.dcdp_ctrl.dc_instance_p[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + FDcDpGeneralCfgInitial(&os_media.dcdp_ctrl, index); } - FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(channel, &os_media); + FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(&os_media,user_cfg.width, user_cfg.height); FASSERT_MSG(NULL == media_event, "Event group exists."); FASSERT_MSG((media_event = xEventGroupCreate()) != NULL, "Create event group failed."); FFreeRTOSMediaIrqSet(&os_config->dcdp_ctrl); @@ -260,24 +298,26 @@ void FFreeRTOSMediaChannelDeinit(u32 id) void FFreeRTOSMediaHpdHandle(void) { u32 index; - u32 ret = FMEDIA_DP_SUCCESS; + u32 ret = FDP_SUCCESS; FFreeRTOSMediaWaitEvent(FMEDIA_EVT_INTR(FMEDIA_CHANNEL_0) | FMEDIA_EVT_INTR(FMEDIA_CHANNEL_1), portMAX_DELAY); - + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (;;) { for (index = 0; index < FDCDP_INSTANCE_NUM; index++) { - if (os_media.dcdp_ctrl.connect_flg[index] == 1) + if (os_media.dcdp_ctrl.is_initialized[index] == FDCDP_NOT_INITIALIZED) { - ret = FDcDpHotPlugConnect(&os_media.dcdp_ctrl, index); + FDcDpCfgInitialize(&os_media.dcdp_ctrl, index); + ret = FDcDpInitial(&os_media.dcdp_ctrl, index, user_cfg.width, user_cfg.height); FFreeRTOSMediaClearEvent(media_event, FMEDIA_EVT_INTR(index)); - if (ret == FMEDIA_DP_SUCCESS) + if (ret == FDP_SUCCESS) { - printf("Hpd task finish , reinit the dp success.\r\n"); + printf("Hpd task finish , reinit the dp success.\r\n"); } - os_media.dcdp_ctrl.connect_flg[index] == 0; + os_media.dcdp_ctrl.is_initialized[index] = FDCDP_IS_INITIALIZED; } + } vTaskDelay(200); } diff --git a/example/peripheral/media/lvgl_ui/configs/e2000d_aarch32_demo_media.config b/example/peripheral/media/lvgl_ui/configs/e2000d_aarch32_demo_media.config index b67648ed..f4eb97da 100644 --- a/example/peripheral/media/lvgl_ui/configs/e2000d_aarch32_demo_media.config +++ b/example/peripheral/media/lvgl_ui/configs/e2000d_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +119,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -147,13 +155,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -359,6 +364,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/configs/e2000d_aarch64_demo_media.config b/example/peripheral/media/lvgl_ui/configs/e2000d_aarch64_demo_media.config index 16568bd4..6e4562ee 100644 --- a/example/peripheral/media/lvgl_ui/configs/e2000d_aarch64_demo_media.config +++ b/example/peripheral/media/lvgl_ui/configs/e2000d_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +113,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -141,13 +149,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -348,6 +353,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/configs/e2000q_aarch32_demo_media.config b/example/peripheral/media/lvgl_ui/configs/e2000q_aarch32_demo_media.config index e9631911..ea7dec49 100644 --- a/example/peripheral/media/lvgl_ui/configs/e2000q_aarch32_demo_media.config +++ b/example/peripheral/media/lvgl_ui/configs/e2000q_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +118,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -146,13 +154,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -358,6 +363,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/configs/e2000q_aarch64_demo_media.config b/example/peripheral/media/lvgl_ui/configs/e2000q_aarch64_demo_media.config index f890f118..0e8fb8e0 100644 --- a/example/peripheral/media/lvgl_ui/configs/e2000q_aarch64_demo_media.config +++ b/example/peripheral/media/lvgl_ui/configs/e2000q_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +112,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -140,13 +148,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -347,6 +352,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch32_firefly_media.config b/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch32_firefly_media.config index c763dc6d..258936e3 100644 --- a/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch32_firefly_media.config +++ b/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch32_firefly_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +117,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -145,13 +153,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -357,6 +362,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch64_firefly_media.config b/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch64_firefly_media.config index 0844bbec..41d72167 100644 --- a/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch64_firefly_media.config +++ b/example/peripheral/media/lvgl_ui/configs/phytiumpi_aarch64_firefly_media.config @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +111,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -139,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -346,6 +351,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/sdkconfig b/example/peripheral/media/lvgl_ui/sdkconfig index 0844bbec..41d72167 100644 --- a/example/peripheral/media/lvgl_ui/sdkconfig +++ b/example/peripheral/media/lvgl_ui/sdkconfig @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +111,7 @@ CONFIG_LOG_DEBUG=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -139,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -346,6 +351,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/lvgl_ui/sdkconfig.h b/example/peripheral/media/lvgl_ui/sdkconfig.h index 65869613..f869c42d 100644 --- a/example/peripheral/media/lvgl_ui/sdkconfig.h +++ b/example/peripheral/media/lvgl_ui/sdkconfig.h @@ -31,6 +31,11 @@ /* CONFIG_BOOT_WITH_FLUSH_CACHE is not set */ /* CONFIG_MMU_DEBUG_PRINTS is not set */ /* end of Arm architecture configuration */ + +/* multi-core system deployment framework */ + +/* CONFIG_USE_MSDF is not set */ +/* end of multi-core system deployment framework */ #define CONFIG_MMU_PAGE_SIZE 0x1000 #define CONFIG_MAX_XLAT_TABLES 256 /* end of Arch configuration */ @@ -44,6 +49,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +102,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -128,11 +135,7 @@ /* CONFIG_USE_PWM is not set */ /* CONFIG_USE_IPC is not set */ #define CONFIG_USE_MEDIA - -/* Media Configuration */ - -#define CONFIG_ENABLE_FDC_DP_USE_LIB -/* end of Media Configuration */ +#define CONFIG_USE_FMEDIA /* CONFIG_USE_SCMI_MHU is not set */ /* CONFIG_USE_I2S is not set */ /* CONFIG_USE_I3C is not set */ @@ -265,6 +268,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -273,6 +277,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -305,6 +311,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/media/lvgl_ui/src/cmd.c b/example/peripheral/media/lvgl_ui/src/cmd.c index 2b90e87e..752836c4 100644 --- a/example/peripheral/media/lvgl_ui/src/cmd.c +++ b/example/peripheral/media/lvgl_ui/src/cmd.c @@ -31,7 +31,6 @@ #include "shell.h" #include "shell_port.h" -#include "fdc_common_hw.h" #include "fdcdp.h" #include "fdp_hw.h" diff --git a/example/peripheral/media/lvgl_ui/src/lv_indev_test.c b/example/peripheral/media/lvgl_ui/src/lv_indev_test.c index 38ddc78f..bc3c981b 100644 --- a/example/peripheral/media/lvgl_ui/src/lv_indev_test.c +++ b/example/peripheral/media/lvgl_ui/src/lv_indev_test.c @@ -41,7 +41,31 @@ #include "lv_indev_port.h" #include "lv_port_disp.h" +#include "fdcdp_reg.h" +#include "fdcdp_crtc.h" +typedef struct +{ + u32 bit_depth; + u32 bpc; + u32 color_depth; + u32 clock_mode; + u32 color_rep; + u32 width; + u32 height; + u32 multi_mode; +} FuserCfg; + +static const FuserCfg user_cfg = { + .bit_depth = 8, + .bpc = 8, + .color_depth = 32, + .clock_mode = 1, + .color_rep = 0, + .width = 800, + .height = 600, + .multi_mode = 0/*0:clone, 1 :horz, 2:vert*/ +}; /************************** Variable Definitions *****************************/ #define FMEDIA_EVT_INTR(index) BIT(index) #define FMEDIA_CHANNEL_0 0 @@ -97,9 +121,9 @@ static void FFreeRTOSMediaHpdConnectCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); - instance_p->connect_flg[index] = 1; + instance_p->is_initialized[index] = FDCDP_IS_INITIALIZED; printf("Dp:%d connect\r\n", index); } @@ -115,8 +139,8 @@ static void FFreeRTOSMediaHpdBreakCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ - instance_p->connect_flg[index] = 0; + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ + instance_p->is_initialized[index] = FDCDP_NOT_INITIALIZED; FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); printf("Dp:%d disconnect\r\n", index); } @@ -132,7 +156,7 @@ static void FFreeRTOSMediaAuxTimeoutCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect timeout\r\n", index); } @@ -147,7 +171,7 @@ static void FFreeRTOSMediaAuxErrorCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect error\r\n", index); } @@ -162,8 +186,6 @@ static void FFreeRTOSMediaIrqSet(FDcDp *instance_p) FASSERT(instance_p != NULL); u32 cpu_id; u32 index; - FMediaIntrConfig intr_config; - memset(&intr_config, 0, sizeof(intr_config)); GetCpuId(&cpu_id); InterruptSetTargetCpus(instance_p->dp_instance_p[0].config.irq_num, cpu_id);/*the dc0 and dc1 have the same num of irq_num*/ @@ -218,17 +240,34 @@ void FFreeRTOSMediaDeviceInit(void) start_index = channel; end_index = channel + 1; } + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (index = start_index; index < end_index; index ++) { - os_media.dcdp_ctrl.user_config[index].width = 800; - os_media.dcdp_ctrl.user_config[index].height = 600; - os_media.dcdp_ctrl.user_config[index].refresh_rate = 60; - os_media.dcdp_ctrl.user_config[index].color_depth = 32; - os_media.dcdp_ctrl.user_config[index].multi_mode = 0; - os_media.dcdp_ctrl.user_config[index].fb_phy = (uintptr)static_frame_buffer_address; - os_media.dcdp_ctrl.user_config[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + FDcDpCfgInitialize(&os_media.dcdp_ctrl,index); + + os_media.dcdp_ctrl.dc_instance_p[index].config = *FDcLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].config = *FDpLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.bit_depth = user_cfg.bit_depth; + + os_media.dcdp_ctrl.dc_instance_p[index].crtc.bpc = user_cfg.bpc; + + os_media.dcdp_ctrl.dc_instance_p[index].color_depth = user_cfg.color_depth; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.clock_mode = user_cfg.clock_mode; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.color_rep_format = user_cfg.color_rep; + + os_media.dcdp_ctrl.dc_instance_p[index].channel = index; + + os_media.dcdp_ctrl.dc_instance_p[index].fb_addr = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + os_media.dcdp_ctrl.dc_instance_p[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + FDcDpGeneralCfgInitial(&os_media.dcdp_ctrl, index); } - FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(channel, &os_media); + FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(&os_media,user_cfg.width, user_cfg.height); FASSERT_MSG(NULL == media_event, "Event group exists."); FASSERT_MSG((media_event = xEventGroupCreate()) != NULL, "Create event group failed."); FFreeRTOSMediaIrqSet(&os_config->dcdp_ctrl); @@ -259,24 +298,25 @@ void FFreeRTOSMediaChannelDeinit(u32 id) */ void FFreeRTOSMediaHpdHandle(void) { - u32 index; - u32 ret = FMEDIA_DP_SUCCESS; + u32 index; + u32 ret = FDP_SUCCESS; FFreeRTOSMediaWaitEvent(FMEDIA_EVT_INTR(FMEDIA_CHANNEL_0) | FMEDIA_EVT_INTR(FMEDIA_CHANNEL_1), portMAX_DELAY); - + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (;;) { for (index = 0; index < FDCDP_INSTANCE_NUM; index++) { - if (os_media.dcdp_ctrl.connect_flg[index] == 1) + if (os_media.dcdp_ctrl.is_initialized[index] == FDCDP_NOT_INITIALIZED) { - ret = FDcDpHotPlugConnect(&os_media.dcdp_ctrl, index); + FDcDpCfgInitialize(&os_media.dcdp_ctrl, index); + ret = FDcDpInitial(&os_media.dcdp_ctrl, index, user_cfg.width, user_cfg.height); FFreeRTOSMediaClearEvent(media_event, FMEDIA_EVT_INTR(index)); - if (ret == FMEDIA_DP_SUCCESS) + if (ret == FDP_SUCCESS) { printf("Hpd task finish , reinit the dp success.\r\n"); } - os_media.dcdp_ctrl.connect_flg[index] == 0; + os_media.dcdp_ctrl.is_initialized[index] = FDCDP_IS_INITIALIZED; } } vTaskDelay(200); diff --git a/example/peripheral/media/media_test/configs/e2000d_aarch32_demo_media.config b/example/peripheral/media/media_test/configs/e2000d_aarch32_demo_media.config index e1f43cc2..4460b984 100644 --- a/example/peripheral/media/media_test/configs/e2000d_aarch32_demo_media.config +++ b/example/peripheral/media/media_test/configs/e2000d_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,12 +113,13 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -147,13 +155,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/e2000d_aarch64_demo_media.config b/example/peripheral/media/media_test/configs/e2000d_aarch64_demo_media.config index b85f6aa5..a5982fcb 100644 --- a/example/peripheral/media/media_test/configs/e2000d_aarch64_demo_media.config +++ b/example/peripheral/media/media_test/configs/e2000d_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -100,12 +107,13 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -141,13 +149,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/e2000q_aarch32_demo_media.config b/example/peripheral/media/media_test/configs/e2000q_aarch32_demo_media.config index 0cb0a46d..8634dc92 100644 --- a/example/peripheral/media/media_test/configs/e2000q_aarch32_demo_media.config +++ b/example/peripheral/media/media_test/configs/e2000q_aarch32_demo_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,12 +112,13 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -146,13 +154,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/e2000q_aarch64_demo_media.config b/example/peripheral/media/media_test/configs/e2000q_aarch64_demo_media.config index 886a5646..9fc7090c 100644 --- a/example/peripheral/media/media_test/configs/e2000q_aarch64_demo_media.config +++ b/example/peripheral/media/media_test/configs/e2000q_aarch64_demo_media.config @@ -29,10 +29,16 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -99,12 +106,13 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -140,13 +148,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_media.config b/example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_media.config index cadc58ad..8effb64c 100644 --- a/example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_media.config +++ b/example/peripheral/media/media_test/configs/phytiumpi_aarch32_firefly_media.config @@ -39,6 +39,12 @@ CONFIG_ARM_MFLOAT_ABI="hard" CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +59,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,12 +111,13 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -145,13 +153,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -343,6 +348,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_media.config b/example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_media.config index 7ecbab11..fe4ecbd2 100644 --- a/example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_media.config +++ b/example/peripheral/media/media_test/configs/phytiumpi_aarch64_firefly_media.config @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -98,12 +105,13 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -139,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/sdkconfig b/example/peripheral/media/media_test/sdkconfig index 75aeebc7..fe4ecbd2 100644 --- a/example/peripheral/media/media_test/sdkconfig +++ b/example/peripheral/media/media_test/sdkconfig @@ -33,6 +33,12 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +# CONFIG_USE_MSDF is not set +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -99,7 +105,7 @@ CONFIG_LOG_DEBUG=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set -# CONFIG_LOG_EXTRA_INFO is not set +CONFIG_LOG_EXTRA_INFO=y # CONFIG_LOG_DISPALY_CORE_NUM is not set # CONFIG_BOOTUP_DEBUG_PRINTS is not set CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y @@ -141,13 +147,7 @@ CONFIG_ENABLE_Pl011_UART=y # CONFIG_USE_PWM is not set # CONFIG_USE_IPC is not set CONFIG_USE_MEDIA=y - -# -# Media Configuration -# -CONFIG_ENABLE_FDC_DP_USE_LIB=y -# end of Media Configuration - +CONFIG_USE_FMEDIA=y # CONFIG_USE_SCMI_MHU is not set # CONFIG_USE_I2S is not set # CONFIG_USE_I3C is not set @@ -303,7 +303,20 @@ CONFIG_FREERTOS_USE_MEDIA=y # Third-party configuration # # CONFIG_USE_LWIP is not set -# CONFIG_USE_LETTER_SHELL is not set +# CONFIG_USE_MBEDTLS is not set +CONFIG_USE_LETTER_SHELL=y + +# +# Letter Shell Configuration +# +CONFIG_LS_PL011_UART=y +CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set +# CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set +# end of Letter Shell Configuration + # CONFIG_USE_AMP is not set # CONFIG_USE_YMODEM is not set # CONFIG_USE_SFUD is not set @@ -324,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/media/media_test/sdkconfig.h b/example/peripheral/media/media_test/sdkconfig.h index cf8454b7..96ec5d44 100644 --- a/example/peripheral/media/media_test/sdkconfig.h +++ b/example/peripheral/media/media_test/sdkconfig.h @@ -31,6 +31,11 @@ /* CONFIG_BOOT_WITH_FLUSH_CACHE is not set */ /* CONFIG_MMU_DEBUG_PRINTS is not set */ /* end of Arm architecture configuration */ + +/* multi-core system deployment framework */ + +/* CONFIG_USE_MSDF is not set */ +/* end of multi-core system deployment framework */ #define CONFIG_MMU_PAGE_SIZE 0x1000 #define CONFIG_MAX_XLAT_TABLES 256 /* end of Arch configuration */ @@ -91,7 +96,7 @@ /* CONFIG_LOG_WARN is not set */ /* CONFIG_LOG_ERROR is not set */ /* CONFIG_LOG_NONE is not set */ -/* CONFIG_LOG_EXTRA_INFO is not set */ +#define CONFIG_LOG_EXTRA_INFO /* CONFIG_LOG_DISPALY_CORE_NUM is not set */ /* CONFIG_BOOTUP_DEBUG_PRINTS is not set */ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG @@ -130,11 +135,7 @@ /* CONFIG_USE_PWM is not set */ /* CONFIG_USE_IPC is not set */ #define CONFIG_USE_MEDIA - -/* Media Configuration */ - -#define CONFIG_ENABLE_FDC_DP_USE_LIB -/* end of Media Configuration */ +#define CONFIG_USE_FMEDIA /* CONFIG_USE_SCMI_MHU is not set */ /* CONFIG_USE_I2S is not set */ /* CONFIG_USE_I3C is not set */ @@ -267,7 +268,18 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ -/* CONFIG_USE_LETTER_SHELL is not set */ +/* CONFIG_USE_MBEDTLS is not set */ +#define CONFIG_USE_LETTER_SHELL + +/* Letter Shell Configuration */ + +#define CONFIG_LS_PL011_UART +#define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ +/* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ +/* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ /* CONFIG_USE_SFUD is not set */ @@ -287,6 +299,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/media/media_test/src/cmd_media.c b/example/peripheral/media/media_test/src/cmd_media.c index ffb7c223..2b1b442a 100644 --- a/example/peripheral/media/media_test/src/cmd_media.c +++ b/example/peripheral/media/media_test/src/cmd_media.c @@ -31,7 +31,6 @@ #include "shell.h" #include "shell_port.h" -#include "fdc_common_hw.h" #include "media_example.h" diff --git a/example/peripheral/media/media_test/src/media_example.c b/example/peripheral/media/media_test/src/media_example.c index ecc59041..acb8ed00 100644 --- a/example/peripheral/media/media_test/src/media_example.c +++ b/example/peripheral/media/media_test/src/media_example.c @@ -40,9 +40,32 @@ #include "fdcdp.h" #include "fdp_hw.h" #include "fdp.h" +#include "fdcdp_reg.h" #include"media_example.h" +#include "fdcdp_crtc.h" +typedef struct +{ + u32 bit_depth; + u32 bpc; + u32 color_depth; + u32 clock_mode; + u32 color_rep; + u32 width; + u32 height; + u32 multi_mode; +} FuserCfg; +static const FuserCfg user_cfg = { + .bit_depth = 8, + .bpc = 8, + .color_depth = 32, + .clock_mode = 1, + .color_rep = 0, + .width = 800, + .height = 600, + .multi_mode = 0/*0:clone, 1 :horz, 2:vert*/ +}; /************************** Variable Definitions *****************************/ #define FMEDIA_EVT_INTR(index) BIT(index) #define FMEDIA_CHANNEL_0 0 @@ -98,14 +121,17 @@ static void FFreeRTOSMediaHpdConnectCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); - instance_p->connect_flg[index] = 1; + instance_p->is_initialized[index] = FDCDP_IS_INITIALIZED; printf("Dp:%d connect\r\n", index); } /** * @name: FFreeRTOSMediaHpdBreakCallback + * + * + * * @msg: the hpd disconnect event * @param {void} *args is the instance of dcdp * @param {u32} index is the channel @@ -115,8 +141,8 @@ static void FFreeRTOSMediaHpdBreakCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ - instance_p->connect_flg[index] = 0; + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ + instance_p->is_initialized[index] = FDCDP_NOT_INITIALIZED; FFreeRTOSMediaSendEvent(FMEDIA_EVT_INTR(index)); printf("Dp:%d disconnect\r\n", index); } @@ -132,7 +158,7 @@ static void FFreeRTOSMediaAuxTimeoutCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect timeout\r\n", index); } @@ -147,7 +173,7 @@ static void FFreeRTOSMediaAuxErrorCallback(void *args, u32 index) { FASSERT(args != NULL); FDcDp *instance_p = (FDcDp *)args; - FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, FDP_TX_INTERRUPT); /*clear interrupt*/ + FDpChannelRegRead(instance_p->dp_instance_p[index].config.dp_channe_base_addr, PHYTIUM_DP_INTERRUPT_STATUS); /*clear interrupt*/ printf("Dp:%d aux connect error\r\n", index); } @@ -201,6 +227,7 @@ static void FDcDpIrqAllEnable(FDcDp *instance_p) */ static void FFreeRTOSMediaInitTask(void) { + FError ret = FDP_SUCCESS; u32 index, start_index, end_index; /*设置用户参数*/ @@ -215,18 +242,35 @@ static void FFreeRTOSMediaInitTask(void) start_index = channel; end_index = channel + 1; } + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (index = start_index; index < end_index; index ++) { - os_media.dcdp_ctrl.user_config[index].width = 640; - os_media.dcdp_ctrl.user_config[index].height = 480; - os_media.dcdp_ctrl.user_config[index].refresh_rate = 60; - os_media.dcdp_ctrl.user_config[index].color_depth = 32; - os_media.dcdp_ctrl.user_config[index].multi_mode = 0; - os_media.dcdp_ctrl.user_config[index].fb_phy = (uintptr)static_frame_buffer_address; - os_media.dcdp_ctrl.user_config[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ - } + FDcDpCfgInitialize(&os_media.dcdp_ctrl,index); + + os_media.dcdp_ctrl.dc_instance_p[index].config = *FDcLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].config = *FDpLookupConfig(index); + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.bit_depth = user_cfg.bit_depth; + + os_media.dcdp_ctrl.dc_instance_p[index].crtc.bpc = user_cfg.bpc; + + os_media.dcdp_ctrl.dc_instance_p[index].color_depth = user_cfg.color_depth; + + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.clock_mode = user_cfg.clock_mode; - FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(channel, &os_media); + os_media.dcdp_ctrl.dp_instance_p[index].trans_config.color_rep_format = user_cfg.color_rep; + + os_media.dcdp_ctrl.dc_instance_p[index].channel = index; + + os_media.dcdp_ctrl.dc_instance_p[index].fb_addr = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + os_media.dcdp_ctrl.dc_instance_p[index].fb_virtual = (uintptr)static_frame_buffer_address ;/*当前例程虚拟地址和物理地址一致,实际需要根据需要进行映射*/ + + FDcDpGeneralCfgInitial(&os_media.dcdp_ctrl, index); + } + + FFreeRTOSMedia *os_config = FFreeRTOSMediaHwInit(&os_media,user_cfg.width, user_cfg.height); FFreeRTOSMediaIrqSet(&os_config->dcdp_ctrl); FDcDpIrqAllEnable(&os_config->dcdp_ctrl); vTaskDelete(NULL); @@ -262,7 +306,7 @@ static void PhyFramebufferWrite(FDcCtrl *instance_p, uintptr offset, u32 length, u32 Index; for (Index = 0; Index < length; Index++) { - FtOut32(os_media.dcdp_ctrl.user_config->fb_virtual + offset + Index * 4, *((u32 *)(config + Index * 4))); + FtOut32(instance_p->fb_virtual + offset + Index * 4, *((u32 *)(config + Index * 4))); } } @@ -312,7 +356,7 @@ FError FMediaDisplayDemo(void) blt_buffer.Green = 0xff; blt_buffer.Blue = 0x0; blt_buffer.reserve = 0; - BltVideoToFill(&instance_p->dc_instance_p[index], &blt_buffer, instance_p->user_config[index].width, instance_p->user_config[index].height); + BltVideoToFill(&instance_p->dc_instance_p[index], &blt_buffer, user_cfg.width, user_cfg.height); } } @@ -322,22 +366,23 @@ static void FFreeRTOSMediaHpdTask(void) u32 index; u32 ret = 0 ; FFreeRTOSMediaWaitEvent(FMEDIA_EVT_INTR(FMEDIA_CHANNEL_0) | FMEDIA_EVT_INTR(FMEDIA_CHANNEL_1), portMAX_DELAY); - + os_media.dcdp_ctrl.multi_mode = user_cfg.multi_mode; for (;;) { for (index = 0; index < FDCDP_INSTANCE_NUM; index++) { - if (os_media.dcdp_ctrl.connect_flg[index] == 1) + if (os_media.dcdp_ctrl.is_initialized[index] == FDCDP_NOT_INITIALIZED) { - ret = FDcDpHotPlugConnect(&os_media.dcdp_ctrl, index); + FDcDpCfgInitialize(&os_media.dcdp_ctrl, index); + ret = FDcDpInitial(&os_media.dcdp_ctrl, index, user_cfg.width, user_cfg.height); FFreeRTOSMediaClearEvent(media_event, FMEDIA_EVT_INTR(index)); - if (ret == FMEDIA_DP_SUCCESS) + if (ret == FDP_SUCCESS) { printf("Hpd task finish , reinit the dp success.\r\n"); } - - os_media.dcdp_ctrl.connect_flg[index] == 0; + os_media.dcdp_ctrl.is_initialized[index] = FDCDP_IS_INITIALIZED; } + } vTaskDelay(200); } diff --git a/example/peripheral/pwm/configs/e2000d_aarch32_demo_pwm.config b/example/peripheral/pwm/configs/e2000d_aarch32_demo_pwm.config index e7e87426..766df661 100644 --- a/example/peripheral/pwm/configs/e2000d_aarch32_demo_pwm.config +++ b/example/peripheral/pwm/configs/e2000d_aarch32_demo_pwm.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/configs/e2000d_aarch64_demo_pwm.config b/example/peripheral/pwm/configs/e2000d_aarch64_demo_pwm.config index c023a8a9..9d4da168 100644 --- a/example/peripheral/pwm/configs/e2000d_aarch64_demo_pwm.config +++ b/example/peripheral/pwm/configs/e2000d_aarch64_demo_pwm.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/configs/e2000q_aarch32_demo_pwm.config b/example/peripheral/pwm/configs/e2000q_aarch32_demo_pwm.config index 2d0aaf30..8439079a 100644 --- a/example/peripheral/pwm/configs/e2000q_aarch32_demo_pwm.config +++ b/example/peripheral/pwm/configs/e2000q_aarch32_demo_pwm.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/configs/e2000q_aarch64_demo_pwm.config b/example/peripheral/pwm/configs/e2000q_aarch64_demo_pwm.config index 09991d84..9c2b5aa3 100644 --- a/example/peripheral/pwm/configs/e2000q_aarch64_demo_pwm.config +++ b/example/peripheral/pwm/configs/e2000q_aarch64_demo_pwm.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/configs/phytiumpi_aarch32_firefly_pwm.config b/example/peripheral/pwm/configs/phytiumpi_aarch32_firefly_pwm.config index f71c8667..00949607 100644 --- a/example/peripheral/pwm/configs/phytiumpi_aarch32_firefly_pwm.config +++ b/example/peripheral/pwm/configs/phytiumpi_aarch32_firefly_pwm.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -343,6 +348,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/configs/phytiumpi_aarch64_firefly_pwm.config b/example/peripheral/pwm/configs/phytiumpi_aarch64_firefly_pwm.config index 9a8c35ee..b7e66f70 100644 --- a/example/peripheral/pwm/configs/phytiumpi_aarch64_firefly_pwm.config +++ b/example/peripheral/pwm/configs/phytiumpi_aarch64_firefly_pwm.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/sdkconfig b/example/peripheral/pwm/sdkconfig index 9a8c35ee..b7e66f70 100644 --- a/example/peripheral/pwm/sdkconfig +++ b/example/peripheral/pwm/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_PWM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/pwm/sdkconfig.h b/example/peripheral/pwm/sdkconfig.h index d4d266fd..d4d89ace 100644 --- a/example/peripheral/pwm/sdkconfig.h +++ b/example/peripheral/pwm/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -265,6 +267,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -273,6 +276,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -293,6 +298,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/qspi/configs/d2000_aarch32_test_qspi.config b/example/peripheral/qspi/configs/d2000_aarch32_test_qspi.config index 055a949e..e0fd9634 100644 --- a/example/peripheral/qspi/configs/d2000_aarch32_test_qspi.config +++ b/example/peripheral/qspi/configs/d2000_aarch32_test_qspi.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/d2000_aarch64_test_qspi.config b/example/peripheral/qspi/configs/d2000_aarch64_test_qspi.config index 49e84af2..a5719225 100644 --- a/example/peripheral/qspi/configs/d2000_aarch64_test_qspi.config +++ b/example/peripheral/qspi/configs/d2000_aarch64_test_qspi.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -321,6 +326,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/e2000d_aarch32_demo_qspi.config b/example/peripheral/qspi/configs/e2000d_aarch32_demo_qspi.config index 69e25ff7..ea632f80 100644 --- a/example/peripheral/qspi/configs/e2000d_aarch32_demo_qspi.config +++ b/example/peripheral/qspi/configs/e2000d_aarch32_demo_qspi.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/e2000d_aarch64_demo_qspi.config b/example/peripheral/qspi/configs/e2000d_aarch64_demo_qspi.config index 1b8ed6fc..f4b57bbd 100644 --- a/example/peripheral/qspi/configs/e2000d_aarch64_demo_qspi.config +++ b/example/peripheral/qspi/configs/e2000d_aarch64_demo_qspi.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/e2000q_aarch32_demo_qspi.config b/example/peripheral/qspi/configs/e2000q_aarch32_demo_qspi.config index d8b57bce..97f8f1b7 100644 --- a/example/peripheral/qspi/configs/e2000q_aarch32_demo_qspi.config +++ b/example/peripheral/qspi/configs/e2000q_aarch32_demo_qspi.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/e2000q_aarch64_demo_qspi.config b/example/peripheral/qspi/configs/e2000q_aarch64_demo_qspi.config index 2b5da9dd..49a52bc9 100644 --- a/example/peripheral/qspi/configs/e2000q_aarch64_demo_qspi.config +++ b/example/peripheral/qspi/configs/e2000q_aarch64_demo_qspi.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/ft2004_aarch32_dsk_qspi.config b/example/peripheral/qspi/configs/ft2004_aarch32_dsk_qspi.config index 52f6d182..48ab86cf 100644 --- a/example/peripheral/qspi/configs/ft2004_aarch32_dsk_qspi.config +++ b/example/peripheral/qspi/configs/ft2004_aarch32_dsk_qspi.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/ft2004_aarch64_dsk_qspi.config b/example/peripheral/qspi/configs/ft2004_aarch64_dsk_qspi.config index 5b193cd6..9efc0cb6 100644 --- a/example/peripheral/qspi/configs/ft2004_aarch64_dsk_qspi.config +++ b/example/peripheral/qspi/configs/ft2004_aarch64_dsk_qspi.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -321,6 +326,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/phytiumpi_aarch32_firefly_qspi.config b/example/peripheral/qspi/configs/phytiumpi_aarch32_firefly_qspi.config index d8d48cc1..c407ffa5 100644 --- a/example/peripheral/qspi/configs/phytiumpi_aarch32_firefly_qspi.config +++ b/example/peripheral/qspi/configs/phytiumpi_aarch32_firefly_qspi.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -343,6 +348,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/configs/phytiumpi_aarch64_firefly_qspi.config b/example/peripheral/qspi/configs/phytiumpi_aarch64_firefly_qspi.config index 217aa275..db21ed6e 100644 --- a/example/peripheral/qspi/configs/phytiumpi_aarch64_firefly_qspi.config +++ b/example/peripheral/qspi/configs/phytiumpi_aarch64_firefly_qspi.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/main.c b/example/peripheral/qspi/main.c index 31e4e911..7c9c08b1 100644 --- a/example/peripheral/qspi/main.c +++ b/example/peripheral/qspi/main.c @@ -40,9 +40,9 @@ void QspiExampleTaskEntry() FFreeRTOSQspiPolledTaskCreate(); FFreeRTOSQspiIndirectTaskCreate(); - +#if defined(CONFIG_E2000D_DEMO_BOARD) || defined(CONFIG_E2000Q_DEMO_BOARD) FFreeRTOSQspiDualFlashTaskCreate(); - +#endif printf("[test_end]\r\n"); vTaskDelete(NULL); diff --git a/example/peripheral/qspi/sdkconfig b/example/peripheral/qspi/sdkconfig index 217aa275..db21ed6e 100644 --- a/example/peripheral/qspi/sdkconfig +++ b/example/peripheral/qspi/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/qspi/sdkconfig.h b/example/peripheral/qspi/sdkconfig.h index b1435460..83a24143 100644 --- a/example/peripheral/qspi/sdkconfig.h +++ b/example/peripheral/qspi/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -265,6 +267,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -273,6 +276,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -293,6 +298,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/sdif/configs/e2000d_aarch32_demo_sdif.config b/example/peripheral/sdif/configs/e2000d_aarch32_demo_sdif.config index f868f81d..6dc0c56e 100644 --- a/example/peripheral/sdif/configs/e2000d_aarch32_demo_sdif.config +++ b/example/peripheral/sdif/configs/e2000d_aarch32_demo_sdif.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -309,6 +311,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -318,6 +321,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -362,6 +367,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/sdif/configs/e2000d_aarch64_demo_sdif.config b/example/peripheral/sdif/configs/e2000d_aarch64_demo_sdif.config index 47e0e796..9819a875 100644 --- a/example/peripheral/sdif/configs/e2000d_aarch64_demo_sdif.config +++ b/example/peripheral/sdif/configs/e2000d_aarch64_demo_sdif.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -298,6 +300,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -307,6 +310,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/sdif/configs/e2000q_aarch32_demo_sdif.config b/example/peripheral/sdif/configs/e2000q_aarch32_demo_sdif.config index e46a6c27..227a1161 100644 --- a/example/peripheral/sdif/configs/e2000q_aarch32_demo_sdif.config +++ b/example/peripheral/sdif/configs/e2000q_aarch32_demo_sdif.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -361,6 +366,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/sdif/configs/e2000q_aarch64_demo_sdif.config b/example/peripheral/sdif/configs/e2000q_aarch64_demo_sdif.config index fed9737b..db164e93 100644 --- a/example/peripheral/sdif/configs/e2000q_aarch64_demo_sdif.config +++ b/example/peripheral/sdif/configs/e2000q_aarch64_demo_sdif.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -350,6 +355,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/sdif/sdkconfig b/example/peripheral/sdif/sdkconfig index fed9737b..db164e93 100644 --- a/example/peripheral/sdif/sdkconfig +++ b/example/peripheral/sdif/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -350,6 +355,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/sdif/sdkconfig.h b/example/peripheral/sdif/sdkconfig.h index 4904d833..dd682f58 100644 --- a/example/peripheral/sdif/sdkconfig.h +++ b/example/peripheral/sdif/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "e2000" #define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 @@ -97,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -263,6 +265,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -271,6 +274,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -308,6 +313,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/spi/configs/e2000d_aarch32_demo_spi.config b/example/peripheral/spi/configs/e2000d_aarch32_demo_spi.config index 7f6c795d..27d95d47 100644 --- a/example/peripheral/spi/configs/e2000d_aarch32_demo_spi.config +++ b/example/peripheral/spi/configs/e2000d_aarch32_demo_spi.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -350,6 +355,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/configs/e2000d_aarch64_demo_spi.config b/example/peripheral/spi/configs/e2000d_aarch64_demo_spi.config index f72ab03c..9232e6a7 100644 --- a/example/peripheral/spi/configs/e2000d_aarch64_demo_spi.config +++ b/example/peripheral/spi/configs/e2000d_aarch64_demo_spi.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/configs/e2000q_aarch32_demo_spi.config b/example/peripheral/spi/configs/e2000q_aarch32_demo_spi.config index 70e77fdb..26a02c4a 100644 --- a/example/peripheral/spi/configs/e2000q_aarch32_demo_spi.config +++ b/example/peripheral/spi/configs/e2000q_aarch32_demo_spi.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -349,6 +354,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/configs/e2000q_aarch64_demo_spi.config b/example/peripheral/spi/configs/e2000q_aarch64_demo_spi.config index 1071b17c..41271d54 100644 --- a/example/peripheral/spi/configs/e2000q_aarch64_demo_spi.config +++ b/example/peripheral/spi/configs/e2000q_aarch64_demo_spi.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/configs/phytiumpi_aarch32_firefly_spi.config b/example/peripheral/spi/configs/phytiumpi_aarch32_firefly_spi.config index 9aaf744b..a578b060 100644 --- a/example/peripheral/spi/configs/phytiumpi_aarch32_firefly_spi.config +++ b/example/peripheral/spi/configs/phytiumpi_aarch32_firefly_spi.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -348,6 +353,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/configs/phytiumpi_aarch64_firefly_spi.config b/example/peripheral/spi/configs/phytiumpi_aarch64_firefly_spi.config index da940498..c549c7c9 100644 --- a/example/peripheral/spi/configs/phytiumpi_aarch64_firefly_spi.config +++ b/example/peripheral/spi/configs/phytiumpi_aarch64_firefly_spi.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/sdkconfig b/example/peripheral/spi/sdkconfig index da940498..c549c7c9 100644 --- a/example/peripheral/spi/sdkconfig +++ b/example/peripheral/spi/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=11 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/spi/sdkconfig.h b/example/peripheral/spi/sdkconfig.h index e2da8616..00d2b530 100644 --- a/example/peripheral/spi/sdkconfig.h +++ b/example/peripheral/spi/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -261,6 +263,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -269,6 +272,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -298,6 +303,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 11 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/timer_tacho/configs/e2000d_aarch32_demo_timer.config b/example/peripheral/timer_tacho/configs/e2000d_aarch32_demo_timer.config index 653168db..633b912d 100644 --- a/example/peripheral/timer_tacho/configs/e2000d_aarch32_demo_timer.config +++ b/example/peripheral/timer_tacho/configs/e2000d_aarch32_demo_timer.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/configs/e2000d_aarch64_demo_timer.config b/example/peripheral/timer_tacho/configs/e2000d_aarch64_demo_timer.config index 5bbff85d..e9eb641f 100644 --- a/example/peripheral/timer_tacho/configs/e2000d_aarch64_demo_timer.config +++ b/example/peripheral/timer_tacho/configs/e2000d_aarch64_demo_timer.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/configs/e2000q_aarch32_demo_timer.config b/example/peripheral/timer_tacho/configs/e2000q_aarch32_demo_timer.config index 8b2055c4..1d65ad62 100644 --- a/example/peripheral/timer_tacho/configs/e2000q_aarch32_demo_timer.config +++ b/example/peripheral/timer_tacho/configs/e2000q_aarch32_demo_timer.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/configs/e2000q_aarch64_demo_timer.config b/example/peripheral/timer_tacho/configs/e2000q_aarch64_demo_timer.config index caa3e1ed..b97ca9c2 100644 --- a/example/peripheral/timer_tacho/configs/e2000q_aarch64_demo_timer.config +++ b/example/peripheral/timer_tacho/configs/e2000q_aarch64_demo_timer.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/configs/phytiumpi_aarch32_firefly_timer.config b/example/peripheral/timer_tacho/configs/phytiumpi_aarch32_firefly_timer.config index a9e93281..c3d7ae80 100644 --- a/example/peripheral/timer_tacho/configs/phytiumpi_aarch32_firefly_timer.config +++ b/example/peripheral/timer_tacho/configs/phytiumpi_aarch32_firefly_timer.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -343,6 +348,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/configs/phytiumpi_aarch64_firefly_timer.config b/example/peripheral/timer_tacho/configs/phytiumpi_aarch64_firefly_timer.config index a88d7f6b..b11568a7 100644 --- a/example/peripheral/timer_tacho/configs/phytiumpi_aarch64_firefly_timer.config +++ b/example/peripheral/timer_tacho/configs/phytiumpi_aarch64_firefly_timer.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/sdkconfig b/example/peripheral/timer_tacho/sdkconfig index a88d7f6b..b11568a7 100644 --- a/example/peripheral/timer_tacho/sdkconfig +++ b/example/peripheral/timer_tacho/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_TIMER=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/timer_tacho/sdkconfig.h b/example/peripheral/timer_tacho/sdkconfig.h index c9819204..326f14e8 100644 --- a/example/peripheral/timer_tacho/sdkconfig.h +++ b/example/peripheral/timer_tacho/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -265,6 +267,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -273,6 +276,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -293,6 +298,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/usb/pusb2_device/configs/e2000d_aarch32_demo_pusb2.config b/example/peripheral/usb/pusb2_device/configs/e2000d_aarch32_demo_pusb2.config index 7ca4ca6e..cf24d8b7 100644 --- a/example/peripheral/usb/pusb2_device/configs/e2000d_aarch32_demo_pusb2.config +++ b/example/peripheral/usb/pusb2_device/configs/e2000d_aarch32_demo_pusb2.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_CHERRY_USB_DEVICE_CDC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_device/configs/e2000d_aarch64_demo_pusb2.config b/example/peripheral/usb/pusb2_device/configs/e2000d_aarch64_demo_pusb2.config index ba34e331..950f243d 100644 --- a/example/peripheral/usb/pusb2_device/configs/e2000d_aarch64_demo_pusb2.config +++ b/example/peripheral/usb/pusb2_device/configs/e2000d_aarch64_demo_pusb2.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -340,6 +345,8 @@ CONFIG_CHERRY_USB_DEVICE_CDC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_device/configs/e2000q_aarch32_demo_pusb2.config b/example/peripheral/usb/pusb2_device/configs/e2000q_aarch32_demo_pusb2.config index 23357541..4213f953 100644 --- a/example/peripheral/usb/pusb2_device/configs/e2000q_aarch32_demo_pusb2.config +++ b/example/peripheral/usb/pusb2_device/configs/e2000q_aarch32_demo_pusb2.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -350,6 +355,8 @@ CONFIG_CHERRY_USB_DEVICE_CDC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_device/configs/e2000q_aarch64_demo_pusb2.config b/example/peripheral/usb/pusb2_device/configs/e2000q_aarch64_demo_pusb2.config index f5edb30e..6c464826 100644 --- a/example/peripheral/usb/pusb2_device/configs/e2000q_aarch64_demo_pusb2.config +++ b/example/peripheral/usb/pusb2_device/configs/e2000q_aarch64_demo_pusb2.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_CHERRY_USB_DEVICE_CDC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_device/main.c b/example/peripheral/usb/pusb2_device/main.c index de4a11e7..b4b4570b 100644 --- a/example/peripheral/usb/pusb2_device/main.c +++ b/example/peripheral/usb/pusb2_device/main.c @@ -26,7 +26,7 @@ #include #include "FreeRTOS.h" #include "fparameters.h" - +#include "task.h" #include "pusb2_mass_storage_example.h" #include "pusb2_virtual_serial_example.h" diff --git a/example/peripheral/usb/pusb2_device/sdkconfig b/example/peripheral/usb/pusb2_device/sdkconfig index f5edb30e..6c464826 100644 --- a/example/peripheral/usb/pusb2_device/sdkconfig +++ b/example/peripheral/usb/pusb2_device/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_CHERRY_USB_DEVICE_CDC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_device/sdkconfig.h b/example/peripheral/usb/pusb2_device/sdkconfig.h index b55a5d7b..e00ffedf 100644 --- a/example/peripheral/usb/pusb2_device/sdkconfig.h +++ b/example/peripheral/usb/pusb2_device/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "e2000" #define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 @@ -97,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -261,6 +263,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -269,6 +272,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -300,6 +305,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/usb/pusb2_device/src/cmd_pusb2.c b/example/peripheral/usb/pusb2_device/src/cmd_pusb2.c index 559763cd..81cf27e5 100644 --- a/example/peripheral/usb/pusb2_device/src/cmd_pusb2.c +++ b/example/peripheral/usb/pusb2_device/src/cmd_pusb2.c @@ -27,7 +27,7 @@ #include "sdkconfig.h" #include "FreeRTOS.h" - +#ifdef CONFIG_USE_LETTER_SHELL #include "../src/shell.h" #include "pusb2_mass_storage_example.h" #include "pusb2_virtual_serial_example.h" @@ -65,4 +65,5 @@ static int USBCmdEntry(int argc, char *argv[]) return ret; } -SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), pusb2, USBCmdEntry, test freertos usb driver); \ No newline at end of file +SHELL_EXPORT_CMD(SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN), pusb2, USBCmdEntry, test freertos usb driver); +#endif \ No newline at end of file diff --git a/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch32_firefly_pusb2.config b/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch32_firefly_pusb2.config index 74a776ed..0ee123f2 100644 --- a/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch32_firefly_pusb2.config +++ b/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch32_firefly_pusb2.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -350,6 +355,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch64_firefly_pusb2.config b/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch64_firefly_pusb2.config index 6e284831..9ef4a36a 100644 --- a/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch64_firefly_pusb2.config +++ b/example/peripheral/usb/pusb2_host/configs/phytiumpi_aarch64_firefly_pusb2.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_host/sdkconfig b/example/peripheral/usb/pusb2_host/sdkconfig index 6e284831..9ef4a36a 100644 --- a/example/peripheral/usb/pusb2_host/sdkconfig +++ b/example/peripheral/usb/pusb2_host/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/pusb2_host/sdkconfig.h b/example/peripheral/usb/pusb2_host/sdkconfig.h index ba5931f4..5d224c9f 100644 --- a/example/peripheral/usb/pusb2_host/sdkconfig.h +++ b/example/peripheral/usb/pusb2_host/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -300,6 +305,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/usb/xhci_pcie/configs/d2000_aarch32_test_cherry_usb.config b/example/peripheral/usb/xhci_pcie/configs/d2000_aarch32_test_cherry_usb.config index e3513e68..8a2ae89e 100644 --- a/example/peripheral/usb/xhci_pcie/configs/d2000_aarch32_test_cherry_usb.config +++ b/example/peripheral/usb/xhci_pcie/configs/d2000_aarch32_test_cherry_usb.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -347,6 +352,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/configs/d2000_aarch64_test_cherry_usb.config b/example/peripheral/usb/xhci_pcie/configs/d2000_aarch64_test_cherry_usb.config index 54b3fb8b..e1d37958 100644 --- a/example/peripheral/usb/xhci_pcie/configs/d2000_aarch64_test_cherry_usb.config +++ b/example/peripheral/usb/xhci_pcie/configs/d2000_aarch64_test_cherry_usb.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -291,6 +293,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -300,6 +303,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch32_demo_cherry_usb.config b/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch32_demo_cherry_usb.config index 4b83e541..d1c667ea 100644 --- a/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch32_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch32_demo_cherry_usb.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -315,6 +317,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -324,6 +327,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -360,6 +365,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch64_demo_cherry_usb.config b/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch64_demo_cherry_usb.config index d2c8ffd5..e793f80d 100644 --- a/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch64_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_pcie/configs/e2000d_aarch64_demo_cherry_usb.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -304,6 +306,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -313,6 +316,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -349,6 +354,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch32_demo_cherry_usb.config b/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch32_demo_cherry_usb.config index 1362725a..3496e4df 100644 --- a/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch32_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch32_demo_cherry_usb.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -359,6 +364,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch64_demo_cherry_usb.config b/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch64_demo_cherry_usb.config index 3f570181..4c0beb63 100644 --- a/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch64_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_pcie/configs/e2000q_aarch64_demo_cherry_usb.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -348,6 +353,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/sdkconfig b/example/peripheral/usb/xhci_pcie/sdkconfig index 3f570181..4c0beb63 100644 --- a/example/peripheral/usb/xhci_pcie/sdkconfig +++ b/example/peripheral/usb/xhci_pcie/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -348,6 +353,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_pcie/sdkconfig.h b/example/peripheral/usb/xhci_pcie/sdkconfig.h index c86ba48f..a6e76815 100644 --- a/example/peripheral/usb/xhci_pcie/sdkconfig.h +++ b/example/peripheral/usb/xhci_pcie/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "e2000" #define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 @@ -97,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -267,6 +269,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -275,6 +278,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -307,6 +312,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/usb/xhci_platform/configs/e2000d_aarch32_demo_cherry_usb.config b/example/peripheral/usb/xhci_platform/configs/e2000d_aarch32_demo_cherry_usb.config index a03c1c8c..25215b6f 100644 --- a/example/peripheral/usb/xhci_platform/configs/e2000d_aarch32_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_platform/configs/e2000d_aarch32_demo_cherry_usb.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -352,6 +357,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/configs/e2000d_aarch64_demo_cherry_usb.config b/example/peripheral/usb/xhci_platform/configs/e2000d_aarch64_demo_cherry_usb.config index 4200f4ee..111eafde 100644 --- a/example/peripheral/usb/xhci_platform/configs/e2000d_aarch64_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_platform/configs/e2000d_aarch64_demo_cherry_usb.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -341,6 +346,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/configs/e2000q_aarch32_demo_cherry_usb.config b/example/peripheral/usb/xhci_platform/configs/e2000q_aarch32_demo_cherry_usb.config index 0e2a1ff6..aa2456ff 100644 --- a/example/peripheral/usb/xhci_platform/configs/e2000q_aarch32_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_platform/configs/e2000q_aarch32_demo_cherry_usb.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/configs/e2000q_aarch64_demo_cherry_usb.config b/example/peripheral/usb/xhci_platform/configs/e2000q_aarch64_demo_cherry_usb.config index f9fc25ef..88bc1da7 100644 --- a/example/peripheral/usb/xhci_platform/configs/e2000q_aarch64_demo_cherry_usb.config +++ b/example/peripheral/usb/xhci_platform/configs/e2000q_aarch64_demo_cherry_usb.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -340,6 +345,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch32_firefly_cherry_usb.config b/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch32_firefly_cherry_usb.config index 2e4121b2..3f046330 100644 --- a/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch32_firefly_cherry_usb.config +++ b/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch32_firefly_cherry_usb.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -350,6 +355,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch64_firefly_cherry_usb.config b/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch64_firefly_cherry_usb.config index 06ba4afd..084530d1 100644 --- a/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch64_firefly_cherry_usb.config +++ b/example/peripheral/usb/xhci_platform/configs/phytiumpi_aarch64_firefly_cherry_usb.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/sdkconfig b/example/peripheral/usb/xhci_platform/sdkconfig index 06ba4afd..084530d1 100644 --- a/example/peripheral/usb/xhci_platform/sdkconfig +++ b/example/peripheral/usb/xhci_platform/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -339,6 +344,8 @@ CONFIG_CHERRY_USB_HOST_HID=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/usb/xhci_platform/sdkconfig.h b/example/peripheral/usb/xhci_platform/sdkconfig.h index c669dea5..ce698dda 100644 --- a/example/peripheral/usb/xhci_platform/sdkconfig.h +++ b/example/peripheral/usb/xhci_platform/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -300,6 +305,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/peripheral/wdt/configs/d2000_aarch32_test_wdt.config b/example/peripheral/wdt/configs/d2000_aarch32_test_wdt.config index 7122b7d8..6f1de1f6 100644 --- a/example/peripheral/wdt/configs/d2000_aarch32_test_wdt.config +++ b/example/peripheral/wdt/configs/d2000_aarch32_test_wdt.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/d2000_aarch64_test_wdt.config b/example/peripheral/wdt/configs/d2000_aarch64_test_wdt.config index 18be75e1..7774a649 100644 --- a/example/peripheral/wdt/configs/d2000_aarch64_test_wdt.config +++ b/example/peripheral/wdt/configs/d2000_aarch64_test_wdt.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -321,6 +326,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/e2000d_aarch32_demo_wdt.config b/example/peripheral/wdt/configs/e2000d_aarch32_demo_wdt.config index dda19905..b2dcfa62 100644 --- a/example/peripheral/wdt/configs/e2000d_aarch32_demo_wdt.config +++ b/example/peripheral/wdt/configs/e2000d_aarch32_demo_wdt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/e2000d_aarch64_demo_wdt.config b/example/peripheral/wdt/configs/e2000d_aarch64_demo_wdt.config index 4da8e392..309a2acf 100644 --- a/example/peripheral/wdt/configs/e2000d_aarch64_demo_wdt.config +++ b/example/peripheral/wdt/configs/e2000d_aarch64_demo_wdt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -334,6 +339,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/e2000q_aarch32_demo_wdt.config b/example/peripheral/wdt/configs/e2000q_aarch32_demo_wdt.config index 8d657e2a..c0df529b 100644 --- a/example/peripheral/wdt/configs/e2000q_aarch32_demo_wdt.config +++ b/example/peripheral/wdt/configs/e2000q_aarch32_demo_wdt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -344,6 +349,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/e2000q_aarch64_demo_wdt.config b/example/peripheral/wdt/configs/e2000q_aarch64_demo_wdt.config index 833feaef..1b3e3b56 100644 --- a/example/peripheral/wdt/configs/e2000q_aarch64_demo_wdt.config +++ b/example/peripheral/wdt/configs/e2000q_aarch64_demo_wdt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -333,6 +338,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/ft2004_aarch32_dsk_wdt.config b/example/peripheral/wdt/configs/ft2004_aarch32_dsk_wdt.config index 89a3d8c1..8c540548 100644 --- a/example/peripheral/wdt/configs/ft2004_aarch32_dsk_wdt.config +++ b/example/peripheral/wdt/configs/ft2004_aarch32_dsk_wdt.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/ft2004_aarch64_dsk_wdt.config b/example/peripheral/wdt/configs/ft2004_aarch64_dsk_wdt.config index d02eaf72..8d9be2aa 100644 --- a/example/peripheral/wdt/configs/ft2004_aarch64_dsk_wdt.config +++ b/example/peripheral/wdt/configs/ft2004_aarch64_dsk_wdt.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -321,6 +326,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/phytiumpi_aarch32_firefly_wdt.config b/example/peripheral/wdt/configs/phytiumpi_aarch32_firefly_wdt.config index 78b319f6..e47c72f3 100644 --- a/example/peripheral/wdt/configs/phytiumpi_aarch32_firefly_wdt.config +++ b/example/peripheral/wdt/configs/phytiumpi_aarch32_firefly_wdt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -343,6 +348,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/configs/phytiumpi_aarch64_firefly_wdt.config b/example/peripheral/wdt/configs/phytiumpi_aarch64_firefly_wdt.config index d5682f4d..6c4234fc 100644 --- a/example/peripheral/wdt/configs/phytiumpi_aarch64_firefly_wdt.config +++ b/example/peripheral/wdt/configs/phytiumpi_aarch64_firefly_wdt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/sdkconfig b/example/peripheral/wdt/sdkconfig index d5682f4d..6c4234fc 100644 --- a/example/peripheral/wdt/sdkconfig +++ b/example/peripheral/wdt/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_WDT=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -332,6 +337,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/peripheral/wdt/sdkconfig.h b/example/peripheral/wdt/sdkconfig.h index 63e89b5d..e482d7f2 100644 --- a/example/peripheral/wdt/sdkconfig.h +++ b/example/peripheral/wdt/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -265,6 +267,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -273,6 +276,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -293,6 +298,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/storage/fatfs/configs/e2000d_aarch32_demo_fatfs.config b/example/storage/fatfs/configs/e2000d_aarch32_demo_fatfs.config index 81e5fc2a..b99641bc 100644 --- a/example/storage/fatfs/configs/e2000d_aarch32_demo_fatfs.config +++ b/example/storage/fatfs/configs/e2000d_aarch32_demo_fatfs.config @@ -62,6 +62,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -121,6 +122,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -318,6 +320,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -327,6 +330,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -426,6 +431,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/configs/e2000d_aarch64_demo_fatfs.config b/example/storage/fatfs/configs/e2000d_aarch64_demo_fatfs.config index 2c9bea66..11fcffef 100644 --- a/example/storage/fatfs/configs/e2000d_aarch64_demo_fatfs.config +++ b/example/storage/fatfs/configs/e2000d_aarch64_demo_fatfs.config @@ -56,6 +56,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -115,6 +116,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -415,6 +420,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/configs/e2000q_aarch32_demo_fatfs.config b/example/storage/fatfs/configs/e2000q_aarch32_demo_fatfs.config index 5f105952..8bce75b1 100644 --- a/example/storage/fatfs/configs/e2000q_aarch32_demo_fatfs.config +++ b/example/storage/fatfs/configs/e2000q_aarch32_demo_fatfs.config @@ -62,6 +62,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -120,6 +121,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -317,6 +319,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -326,6 +329,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -425,6 +430,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/configs/e2000q_aarch64_demo_fatfs.config b/example/storage/fatfs/configs/e2000q_aarch64_demo_fatfs.config index 5eed3665..151b57c7 100644 --- a/example/storage/fatfs/configs/e2000q_aarch64_demo_fatfs.config +++ b/example/storage/fatfs/configs/e2000q_aarch64_demo_fatfs.config @@ -56,6 +56,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -114,6 +115,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -414,6 +419,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/configs/phytiumpi_aarch32_firefly_fatfs.config b/example/storage/fatfs/configs/phytiumpi_aarch32_firefly_fatfs.config index 2933f9b3..9b0947d8 100644 --- a/example/storage/fatfs/configs/phytiumpi_aarch32_firefly_fatfs.config +++ b/example/storage/fatfs/configs/phytiumpi_aarch32_firefly_fatfs.config @@ -62,6 +62,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -119,6 +120,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -316,6 +318,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -325,6 +328,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -400,6 +405,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/configs/phytiumpi_aarch64_firefly_fatfs.config b/example/storage/fatfs/configs/phytiumpi_aarch64_firefly_fatfs.config index e3c9e75b..2e80e47a 100644 --- a/example/storage/fatfs/configs/phytiumpi_aarch64_firefly_fatfs.config +++ b/example/storage/fatfs/configs/phytiumpi_aarch64_firefly_fatfs.config @@ -56,6 +56,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -113,6 +114,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -389,6 +394,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/sdkconfig b/example/storage/fatfs/sdkconfig index e3c9e75b..2e80e47a 100644 --- a/example/storage/fatfs/sdkconfig +++ b/example/storage/fatfs/sdkconfig @@ -56,6 +56,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -113,6 +114,7 @@ CONFIG_LOG_EXTRA_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -389,6 +394,8 @@ CONFIG_FSL_SDMMC_ENABLE_MMC=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/fatfs/sdkconfig.h b/example/storage/fatfs/sdkconfig.h index 1c6a14c8..366cc48a 100644 --- a/example/storage/fatfs/sdkconfig.h +++ b/example/storage/fatfs/sdkconfig.h @@ -50,6 +50,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -102,6 +103,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -268,6 +270,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -276,6 +279,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -340,6 +345,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/storage/qspi_spiffs/configs/d2000_aarch32_test_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/d2000_aarch32_test_qspi_spiffs.config index 4da5f876..3222e43c 100644 --- a/example/storage/qspi_spiffs/configs/d2000_aarch32_test_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/d2000_aarch32_test_qspi_spiffs.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/d2000_aarch64_test_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/d2000_aarch64_test_qspi_spiffs.config index 41ec7b25..e175ff0d 100644 --- a/example/storage/qspi_spiffs/configs/d2000_aarch64_test_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/d2000_aarch64_test_qspi_spiffs.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -340,6 +345,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/e2000d_aarch32_demo_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/e2000d_aarch32_demo_qspi_spiffs.config index 3aa97215..d31989aa 100644 --- a/example/storage/qspi_spiffs/configs/e2000d_aarch32_demo_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/e2000d_aarch32_demo_qspi_spiffs.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -314,6 +316,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -323,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -364,6 +369,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/e2000d_aarch64_demo_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/e2000d_aarch64_demo_qspi_spiffs.config index fda5d31c..6b7aad19 100644 --- a/example/storage/qspi_spiffs/configs/e2000d_aarch64_demo_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/e2000d_aarch64_demo_qspi_spiffs.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -303,6 +305,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -312,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -353,6 +358,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/e2000q_aarch32_demo_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/e2000q_aarch32_demo_qspi_spiffs.config index 9ead099f..b0fa43f3 100644 --- a/example/storage/qspi_spiffs/configs/e2000q_aarch32_demo_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/e2000q_aarch32_demo_qspi_spiffs.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -313,6 +315,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -322,6 +325,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -363,6 +368,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/e2000q_aarch64_demo_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/e2000q_aarch64_demo_qspi_spiffs.config index 5df333ea..a471bdca 100644 --- a/example/storage/qspi_spiffs/configs/e2000q_aarch64_demo_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/e2000q_aarch64_demo_qspi_spiffs.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -302,6 +304,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -311,6 +314,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -352,6 +357,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/ft2004_aarch32_dsk_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/ft2004_aarch32_dsk_qspi_spiffs.config index ead46055..dfbe33b9 100644 --- a/example/storage/qspi_spiffs/configs/ft2004_aarch32_dsk_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/ft2004_aarch32_dsk_qspi_spiffs.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/ft2004_aarch64_dsk_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/ft2004_aarch64_dsk_qspi_spiffs.config index f4520b95..7bd3de36 100644 --- a/example/storage/qspi_spiffs/configs/ft2004_aarch64_dsk_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/ft2004_aarch64_dsk_qspi_spiffs.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -290,6 +292,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -299,6 +302,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -340,6 +345,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/phytiumpi_aarch32_firefly_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/phytiumpi_aarch32_firefly_qspi_spiffs.config index 67abc49b..474fee9c 100644 --- a/example/storage/qspi_spiffs/configs/phytiumpi_aarch32_firefly_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/phytiumpi_aarch32_firefly_qspi_spiffs.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -312,6 +314,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -321,6 +324,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -362,6 +367,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/configs/phytiumpi_aarch64_firefly_qspi_spiffs.config b/example/storage/qspi_spiffs/configs/phytiumpi_aarch64_firefly_qspi_spiffs.config index 74a59d0f..aca964ca 100644 --- a/example/storage/qspi_spiffs/configs/phytiumpi_aarch64_firefly_qspi_spiffs.config +++ b/example/storage/qspi_spiffs/configs/phytiumpi_aarch64_firefly_qspi_spiffs.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/sdkconfig b/example/storage/qspi_spiffs/sdkconfig index 74a59d0f..aca964ca 100644 --- a/example/storage/qspi_spiffs/sdkconfig +++ b/example/storage/qspi_spiffs/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -301,6 +303,7 @@ CONFIG_FREERTOS_USE_QSPI=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -310,6 +313,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -351,6 +356,8 @@ CONFIG_SPIFFS_ON_FQSPI_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/qspi_spiffs/sdkconfig.h b/example/storage/qspi_spiffs/sdkconfig.h index 508af194..3d48d14f 100644 --- a/example/storage/qspi_spiffs/sdkconfig.h +++ b/example/storage/qspi_spiffs/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -265,6 +267,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -273,6 +276,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -308,6 +313,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/storage/spim_spiffs/configs/e2000d_aarch32_demo_spi_spiffs.config b/example/storage/spim_spiffs/configs/e2000d_aarch32_demo_spi_spiffs.config index 194dfe27..5bac3584 100644 --- a/example/storage/spim_spiffs/configs/e2000d_aarch32_demo_spi_spiffs.config +++ b/example/storage/spim_spiffs/configs/e2000d_aarch32_demo_spi_spiffs.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -308,6 +310,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -317,6 +320,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -358,6 +363,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/configs/e2000d_aarch64_demo_spi_spiffs.config b/example/storage/spim_spiffs/configs/e2000d_aarch64_demo_spi_spiffs.config index 42ae0689..c531be13 100644 --- a/example/storage/spim_spiffs/configs/e2000d_aarch64_demo_spi_spiffs.config +++ b/example/storage/spim_spiffs/configs/e2000d_aarch64_demo_spi_spiffs.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -297,6 +299,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -306,6 +309,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -347,6 +352,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/configs/e2000q_aarch32_demo_spi_spiffs.config b/example/storage/spim_spiffs/configs/e2000q_aarch32_demo_spi_spiffs.config index d34a196f..c8336abd 100644 --- a/example/storage/spim_spiffs/configs/e2000q_aarch32_demo_spi_spiffs.config +++ b/example/storage/spim_spiffs/configs/e2000q_aarch32_demo_spi_spiffs.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -357,6 +362,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/configs/e2000q_aarch64_demo_spi_spiffs.config b/example/storage/spim_spiffs/configs/e2000q_aarch64_demo_spi_spiffs.config index 96b2f120..e126a715 100644 --- a/example/storage/spim_spiffs/configs/e2000q_aarch64_demo_spi_spiffs.config +++ b/example/storage/spim_spiffs/configs/e2000q_aarch64_demo_spi_spiffs.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -346,6 +351,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/configs/phytiumpi_aarch32_firefly_spi_spiffs.config b/example/storage/spim_spiffs/configs/phytiumpi_aarch32_firefly_spi_spiffs.config index 214c1c47..18fb4b0e 100644 --- a/example/storage/spim_spiffs/configs/phytiumpi_aarch32_firefly_spi_spiffs.config +++ b/example/storage/spim_spiffs/configs/phytiumpi_aarch32_firefly_spi_spiffs.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -356,6 +361,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/configs/phytiumpi_aarch64_firefly_spi_spiffs.config b/example/storage/spim_spiffs/configs/phytiumpi_aarch64_firefly_spi_spiffs.config index 1a65b102..df4eb455 100644 --- a/example/storage/spim_spiffs/configs/phytiumpi_aarch64_firefly_spi_spiffs.config +++ b/example/storage/spim_spiffs/configs/phytiumpi_aarch64_firefly_spi_spiffs.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/sdkconfig b/example/storage/spim_spiffs/sdkconfig index 1a65b102..df4eb455 100644 --- a/example/storage/spim_spiffs/sdkconfig +++ b/example/storage/spim_spiffs/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_FSPIM=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -345,6 +350,8 @@ CONFIG_SPIFFS_ON_FSPIM_SFUD=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/storage/spim_spiffs/sdkconfig.h b/example/storage/spim_spiffs/sdkconfig.h index 5359a0be..bd50c132 100644 --- a/example/storage/spim_spiffs/sdkconfig.h +++ b/example/storage/spim_spiffs/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -261,6 +263,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -269,6 +272,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -304,6 +309,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/system/amp/README.md b/example/system/amp/README.md index c7847098..7f37d93e 100644 --- a/example/system/amp/README.md +++ b/example/system/amp/README.md @@ -15,7 +15,7 @@ 7. 例程介绍: -- `openamp`:本例程演示了如何使用openamp库在多核片上运行。 +- `openamp`:本例程演示了如何使用openamp库在多核上运行。 - `openamp_for_linux`:本例程演示了如何使用编译好的基于freertos的 openamp例程镜像,在linux系统加载下运行(需要linux系统支持)。 > 注:建议学习顺序:先裸机standalone,再freertos,最后linux。 diff --git a/example/system/amp/openamp/common/openamp_configs.h b/example/system/amp/openamp/common/openamp_configs.h index 3be1b14d..b67ffa21 100644 --- a/example/system/amp/openamp/common/openamp_configs.h +++ b/example/system/amp/openamp/common/openamp_configs.h @@ -13,7 +13,7 @@ * * FilePath: openamp_configs.h * Created Date: 2024-05-06 19:20:51 - * Last Modified: 2024-07-22 14:49:16 + * Last Modified: 2024-12-02 19:51:28 * Description: This file is for * * Modify History: @@ -43,13 +43,20 @@ static u32 remoteproc_online_mask = 0 ; #define RPMSG_SERVICE_00_NAME "rpmsg_service_name_00" /* 从核发送消息时,需要指定发送的cpu的核号,用来确定软件中断的发送到哪个核上 */ -#ifdef CONFIG_TARGET_E2000D -#define MASTER_DRIVER_CORE 1 /* 与amp_config.json中的管理(主)核配置保持一致 */ +#if defined(CONFIG_TARGET_E2000D) || defined(CONFIG_TARGET_D2000) +#define MASTER_DRIVER_CORE 0 /* 与amp_config.json中的管理(主)核配置保持一致 */ #else #define MASTER_DRIVER_CORE 2 /* 与amp_config.json中的管理(主)核配置保持一致 */ #endif -/* 主核给从核发送消息时,需要指定接收的cpu的核号,用来确定软件中断的发送到哪个核上,以及主核指定启动镜像在那个核心上运行 */ + +/* 主核发送消息时,需要指定接收的cpu的核号,用来确定软件中断的发送到哪个核上,以及主核指定启动镜像在那个核心上运行 */ +#if defined(CONFIG_TARGET_D2000) +#define SLAVE_DEVICE_CORE_00 4 +#elif defined(CONFIG_TARGET_E2000D) +#define SLAVE_DEVICE_CORE_00 1 +#else #define SLAVE_DEVICE_CORE_00 0 +#endif #ifdef __cplusplus } diff --git a/example/system/amp/openamp/device_core/configs/d2000_aarch32_test_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/d2000_aarch32_test_openamp_device_core.config index 35211e2f..1d45ac71 100644 --- a/example/system/amp/openamp/device_core/configs/d2000_aarch32_test_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/d2000_aarch32_test_openamp_device_core.config @@ -37,6 +37,7 @@ CONFIG_ARM_MFLOAT_ABI="hard" # end of Compiler configuration CONFIG_USE_L3CACHE=y +# CONFIG_DISABLE_L3CACHE is not set # CONFIG_USE_AARCH64_L1_TO_AARCH32 is not set # end of Arm architecture configuration @@ -54,6 +55,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +101,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -327,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/d2000_aarch64_test_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/d2000_aarch64_test_openamp_device_core.config index 18bab938..d0a55952 100644 --- a/example/system/amp/openamp/device_core/configs/d2000_aarch64_test_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/d2000_aarch64_test_openamp_device_core.config @@ -30,6 +30,7 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # end of Compiler configuration CONFIG_USE_L3CACHE=y +# CONFIG_DISABLE_L3CACHE is not set # CONFIG_BOOT_WITH_FLUSH_CACHE is not set # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration @@ -48,6 +49,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +95,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +286,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -316,6 +320,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/e2000d_aarch32_demo_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/e2000d_aarch32_demo_openamp_device_core.config index e4a498fa..a76717d6 100644 --- a/example/system/amp/openamp/device_core/configs/e2000d_aarch32_demo_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/e2000d_aarch32_demo_openamp_device_core.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -340,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/e2000d_aarch64_demo_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/e2000d_aarch64_demo_openamp_device_core.config index 6c5a55b2..087f8f28 100644 --- a/example/system/amp/openamp/device_core/configs/e2000d_aarch64_demo_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/e2000d_aarch64_demo_openamp_device_core.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -329,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/e2000q_aarch32_demo_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/e2000q_aarch32_demo_openamp_device_core.config index 716d4b1b..df080ffc 100644 --- a/example/system/amp/openamp/device_core/configs/e2000q_aarch32_demo_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/e2000q_aarch32_demo_openamp_device_core.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -339,6 +342,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/e2000q_aarch64_demo_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/e2000q_aarch64_demo_openamp_device_core.config index e4d4da2a..07b54827 100644 --- a/example/system/amp/openamp/device_core/configs/e2000q_aarch64_demo_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/e2000q_aarch64_demo_openamp_device_core.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -328,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/phytiumpi_aarch32_firefly_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/phytiumpi_aarch32_firefly_openamp_device_core.config index d3c441bf..4f68c26f 100644 --- a/example/system/amp/openamp/device_core/configs/phytiumpi_aarch32_firefly_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/phytiumpi_aarch32_firefly_openamp_device_core.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -338,6 +341,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/configs/phytiumpi_aarch64_firefly_openamp_device_core.config b/example/system/amp/openamp/device_core/configs/phytiumpi_aarch64_firefly_openamp_device_core.config index 3c397fe8..dd872993 100644 --- a/example/system/amp/openamp/device_core/configs/phytiumpi_aarch64_firefly_openamp_device_core.config +++ b/example/system/amp/openamp/device_core/configs/phytiumpi_aarch64_firefly_openamp_device_core.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -327,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/sdkconfig b/example/system/amp/openamp/device_core/sdkconfig index 3c397fe8..07b54827 100644 --- a/example/system/amp/openamp/device_core/sdkconfig +++ b/example/system/amp/openamp/device_core/sdkconfig @@ -40,14 +40,16 @@ CONFIG_MAX_XLAT_TABLES=256 # # Soc configuration # -CONFIG_TARGET_PHYTIUMPI=y -# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_PHYTIUMPI is not set +CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_E2000D is not set # CONFIG_TARGET_E2000S is not set # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set -CONFIG_SOC_NAME="phytiumpi" +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="e2000" +CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 @@ -62,7 +64,7 @@ CONFIG_DEFAULT_DEBUG_PRINT_UART1=y # # Board Configuration # -CONFIG_BOARD_NAME="firefly" +CONFIG_BOARD_NAME="demo" # CONFIG_USE_SPI_IOPAD is not set # CONFIG_USE_GPIO_IOPAD is not set # CONFIG_USE_CAN_IOPAD is not set @@ -72,7 +74,7 @@ CONFIG_BOARD_NAME="firefly" # CONFIG_USE_TACHO_IOPAD is not set # CONFIG_USE_UART_IOPAD is not set # CONFIG_USE_THIRD_PARTY_IOPAD is not set -CONFIG_FIREFLY_DEMO_BOARD=y +CONFIG_E2000Q_DEMO_BOARD=y # # IO mux configuration when board start up @@ -104,6 +106,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -327,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/device_core/sdkconfig.h b/example/system/amp/openamp/device_core/sdkconfig.h index 582b2ba4..3b7f29e9 100644 --- a/example/system/amp/openamp/device_core/sdkconfig.h +++ b/example/system/amp/openamp/device_core/sdkconfig.h @@ -37,14 +37,16 @@ /* Soc configuration */ -#define CONFIG_TARGET_PHYTIUMPI -/* CONFIG_TARGET_E2000Q is not set */ +/* CONFIG_TARGET_PHYTIUMPI is not set */ +#define CONFIG_TARGET_E2000Q /* CONFIG_TARGET_E2000D is not set */ /* CONFIG_TARGET_E2000S is not set */ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ -#define CONFIG_SOC_NAME "phytiumpi" +/* CONFIG_TARGET_QEMU_VIRT is not set */ +#define CONFIG_SOC_NAME "e2000" +#define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 #define CONFIG_F32BIT_MEMORY_LENGTH 0x80000000 @@ -58,7 +60,7 @@ /* Board Configuration */ -#define CONFIG_BOARD_NAME "firefly" +#define CONFIG_BOARD_NAME "demo" /* CONFIG_USE_SPI_IOPAD is not set */ /* CONFIG_USE_GPIO_IOPAD is not set */ /* CONFIG_USE_CAN_IOPAD is not set */ @@ -68,7 +70,7 @@ /* CONFIG_USE_TACHO_IOPAD is not set */ /* CONFIG_USE_UART_IOPAD is not set */ /* CONFIG_USE_THIRD_PARTY_IOPAD is not set */ -#define CONFIG_FIREFLY_DEMO_BOARD +#define CONFIG_E2000Q_DEMO_BOARD /* IO mux configuration when board start up */ @@ -96,6 +98,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG /* CONFIG_INTERRUPT_ROLE_MASTER is not set */ #define CONFIG_INTERRUPT_ROLE_SLAVE +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +263,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ /* CONFIG_USE_LETTER_SHELL is not set */ #define CONFIG_USE_AMP #define CONFIG_USE_LIBMETAL @@ -290,6 +294,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/system/amp/openamp/driver_core/README.md b/example/system/amp/openamp/driver_core/README.md index 2c41951f..d4a582f6 100644 --- a/example/system/amp/openamp/driver_core/README.md +++ b/example/system/amp/openamp/driver_core/README.md @@ -77,7 +77,7 @@ rpmsg-design: - 具体使用方法为: - - 在 /example/system/amp/openamp 对应 目录 下 + - 在 /example/system/amp/openamp/driver_core 目录 下 - 执行上述指令 ### 2.3 构建和下载 @@ -102,16 +102,15 @@ rpmsg-design: #### 用户自定义修改配置项 -- 因为多核采用的是脚本自动寻找 `amp_config.json` 文件描述的工程目录,加载配置好的配置项(在目标路径的 configs 目录下),进行编译。所以,需要先保存修改好的配置项到默认配置目录中。 +- 因为多核采用的是脚本自动寻找 `amp_config.json` 文件描述的工程目录,加载配置好的默认配置项(在目标路径的 configs 目录下),进行编译。所以,需要先保存修改好的配置项到默认配置目录中。 -- 可以单个进入子工程目录中,单个调试完工程后再组合编译(遇到启动问题,推荐此构建方式排查调试多核启动问题)(注意:aarch32模式单个调试启动需要打开CONFIG_USE_AARCH64_L1_TO_AARCH32)。 +- 可以单个进入工程目录中,单个调试完工程后再组合编译(遇到启动问题,推荐此构建方式排查调试多核启动问题)(注意:aarch32模式单个调试启动需要打开CONFIG_USE_AARCH64_L1_TO_AARCH32)。 > aarch32需要注意的点 ![USE_AARCH64_L1_TO_AARCH32](./fig/OpenAMPConfig0.png) -- 单个工程目录中使用`make backup_kconfig`保存调试好的AARCH32配置到默认配置,别忘了在工程中关闭CONFIG_USE_AARCH64_L1_TO_AARCH32,否则会导致启动失败。 -- 注意:混合异构部署启动中,各个工程都不需要打开(可以看工程的configs目录下凡是aarch32的配置都没打开),否则会导致启动失败,因为bootcode启动阶段已经做了此转换操作。 +- 单个工程目录中使用`make backup_kconfig`保存调试好的AARCH32配置到默认配置,如果是子工程(`amp_config.json`非bootstrap配置项)别忘了在工程中关闭CONFIG_USE_AARCH64_L1_TO_AARCH32,否则会导致启动失败。 #### 编译 @@ -151,16 +150,16 @@ rpmsg-design: 2.4 输入 'openamp' 运行openamp 命令程序示例,结果显示为: -![1677585960509](./fig/1677585960509.png) +![openamp64](./fig/openamp64.png) - 其中 "openamp auto" 表示命令的完整格式,一次性测试4个demo,红色方框为核2调用函数启动核心0的过程 -![20230512192325](./fig/20230512192325.png) +![openamp64_auto](./fig/openamp64_auto.png) - 其中 "Test Results:Error count =" 表示通信过程中出现错误的次数 -![20231017160632](./fig/20231017160632.png) +![Test64_Results](./fig/Test64_Results.png) #### aarch32 程序测试 (freeRTOS 间) @@ -190,15 +189,15 @@ rpmsg-design: 2.5 输入 'openamp' 运行openamp 命令程序示例 -![20230512195526](./fig/20230512195526.png) +![openamp32](./fig/openamp32.png) 2.6 输入 'openamp auto' 表示命令的完整格式,一次性测试4个demo -![20230512200435](./fig/20230512200435.png) +![openamp32_auto](./fig/openamp32_auto.png) - 其中 "Test Results:Error count =" 表示通信过程中出现错误的次数 -![20231017165755](./fig/20231017165755.png) +![Test32_Results](./fig/Test32_Results.png) ## 3. 如何解决问题 (Q&A) @@ -214,3 +213,4 @@ rpmsg-design: - 2023-05-12 :v0.1.0 初始化项目 - 2023-05-31 : v0.1.1 增加自动加载从核elf并启动的功能 - 2024-07-18 : v0.1.2 完善openamp生命周期管理,修改配置方式 +- 2024-12-03 : v0.1.3 增加新多元异构系统架构支持,完善readme文档 diff --git a/example/system/amp/openamp/driver_core/amp_config.json b/example/system/amp/openamp/driver_core/amp_config.json index d1806167..4fb9d2fe 100644 --- a/example/system/amp/openamp/driver_core/amp_config.json +++ b/example/system/amp/openamp/driver_core/amp_config.json @@ -22,74 +22,50 @@ { "config0":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"e2000q_aarch64_demo_openamp_device_core.config"], - "path1":["./",2,1,"e2000q_aarch64_demo_openamp_driver_core.config"] + "bootstrap":["./",2,1,"e2000q_aarch64_demo_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"e2000q_aarch64_demo_openamp_device_core.config"] } ], "config1":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"e2000q_aarch32_demo_openamp_device_core.config"], - "path1":["./",2,1,"e2000q_aarch32_demo_openamp_driver_core.config"] + "bootstrap":["./",2,1,"e2000q_aarch32_demo_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"e2000q_aarch32_demo_openamp_device_core.config"] } ], "config2":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"e2000d_aarch64_demo_openamp_device_core.config"], - "path1":["./",1,1,"e2000d_aarch64_demo_openamp_driver_core.config"] + "bootstrap":["./",0,1,"e2000d_aarch64_demo_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"e2000d_aarch64_demo_openamp_device_core.config"] } ], "config3":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"e2000d_aarch32_demo_openamp_device_core.config"], - "path1":["./",1,1,"e2000d_aarch32_demo_openamp_driver_core.config"] + "bootstrap":["./",0,1,"e2000d_aarch32_demo_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"e2000d_aarch32_demo_openamp_device_core.config"] } ], "config4":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"phytiumpi_aarch64_firefly_openamp_device_core.config"], - "path1":["./",2,1,"phytiumpi_aarch64_firefly_openamp_driver_core.config"] + "bootstrap":["./",2,1,"phytiumpi_aarch64_firefly_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"phytiumpi_aarch64_firefly_openamp_device_core.config"] } ], "config5":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"phytiumpi_aarch32_firefly_openamp_device_core.config"], - "path1":["./",2,1,"phytiumpi_aarch32_firefly_openamp_driver_core.config"] + "bootstrap":["./",2,1,"phytiumpi_aarch32_firefly_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"phytiumpi_aarch32_firefly_openamp_device_core.config"] } ], "config6":[ { - "bootstrap":"0x90120000" - }, - { - "path0":["../device_core",10000,0,"d2000_aarch64_test_openamp_device_core.config"], - "path1":["./",2,1,"d2000_aarch64_test_openamp_driver_core.config"] + "bootstrap":["./",0,1,"d2000_aarch64_test_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"d2000_aarch64_test_openamp_device_core.config"] } ], "config7":[ { - "bootstrap":"0x90120000" - }, - { - "path1":["../device_core",10000,0,"d2000_aarch32_test_openamp_device_core.config"], - "path0":["./",2,1,"d2000_aarch32_test_openamp_driver_core.config"] + "bootstrap":["./",0,1,"d2000_aarch32_test_openamp_driver_core.config"], + "path0":["../device_core",10000,0,"d2000_aarch32_test_openamp_device_core.config"] } ] } diff --git a/example/system/amp/openamp/driver_core/configs/d2000_aarch32_test_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/d2000_aarch32_test_openamp_driver_core.config index 38ec6567..af96a918 100644 --- a/example/system/amp/openamp/driver_core/configs/d2000_aarch32_test_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/d2000_aarch32_test_openamp_driver_core.config @@ -36,10 +36,20 @@ CONFIG_ARM_MFLOAT_ABI="hard" # end of Fpu configuration # end of Compiler configuration -# CONFIG_USE_L3CACHE is not set -# CONFIG_USE_AARCH64_L1_TO_AARCH32 is not set +CONFIG_USE_L3CACHE=y +CONFIG_DISABLE_L3CACHE=y +CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=0 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -54,6 +64,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -87,9 +98,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -99,6 +110,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +306,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +316,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -337,6 +352,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/d2000_aarch64_test_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/d2000_aarch64_test_openamp_driver_core.config index cab1b7c6..18ca36e8 100644 --- a/example/system/amp/openamp/driver_core/configs/d2000_aarch64_test_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/d2000_aarch64_test_openamp_driver_core.config @@ -29,11 +29,21 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_GCC_CODE_MODEL_LARGE is not set # end of Compiler configuration -# CONFIG_USE_L3CACHE is not set -# CONFIG_BOOT_WITH_FLUSH_CACHE is not set +CONFIG_USE_L3CACHE=y +CONFIG_DISABLE_L3CACHE=y +CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=0 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -48,6 +58,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -81,9 +92,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -93,6 +104,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +295,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +305,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -326,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/e2000d_aarch32_demo_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/e2000d_aarch32_demo_openamp_driver_core.config index d7ef0d31..a0102645 100644 --- a/example/system/amp/openamp/driver_core/configs/e2000d_aarch32_demo_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/e2000d_aarch32_demo_openamp_driver_core.config @@ -36,9 +36,18 @@ CONFIG_ARM_MFLOAT_ABI="hard" # end of Fpu configuration # end of Compiler configuration -# CONFIG_USE_AARCH64_L1_TO_AARCH32 is not set +CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=0 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +62,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -100,9 +110,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -112,6 +122,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +318,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +328,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -350,6 +364,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/e2000d_aarch64_demo_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/e2000d_aarch64_demo_openamp_driver_core.config index cb7802c6..883cd5f5 100644 --- a/example/system/amp/openamp/driver_core/configs/e2000d_aarch64_demo_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/e2000d_aarch64_demo_openamp_driver_core.config @@ -33,6 +33,15 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=0 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +56,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -94,9 +104,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -106,6 +116,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -339,6 +353,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/e2000q_aarch32_demo_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/e2000q_aarch32_demo_openamp_driver_core.config index 9ac578fb..17d4c7c1 100644 --- a/example/system/amp/openamp/driver_core/configs/e2000q_aarch32_demo_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/e2000q_aarch32_demo_openamp_driver_core.config @@ -36,9 +36,18 @@ CONFIG_ARM_MFLOAT_ABI="hard" # end of Fpu configuration # end of Compiler configuration -# CONFIG_USE_AARCH64_L1_TO_AARCH32 is not set +CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=2 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +62,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -99,9 +109,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -111,6 +121,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +317,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +327,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -349,6 +363,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/e2000q_aarch64_demo_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/e2000q_aarch64_demo_openamp_driver_core.config index 65b4dad0..589235d2 100644 --- a/example/system/amp/openamp/driver_core/configs/e2000q_aarch64_demo_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/e2000q_aarch64_demo_openamp_driver_core.config @@ -33,6 +33,15 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=2 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +56,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -93,9 +103,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -105,6 +115,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +306,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +316,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -338,6 +352,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch32_firefly_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch32_firefly_openamp_driver_core.config index 9997670f..de426e59 100644 --- a/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch32_firefly_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch32_firefly_openamp_driver_core.config @@ -36,9 +36,18 @@ CONFIG_ARM_MFLOAT_ABI="hard" # end of Fpu configuration # end of Compiler configuration -# CONFIG_USE_AARCH64_L1_TO_AARCH32 is not set +CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=2 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_FMMU_NUM_L2_TABLES=256 # end of Arch configuration @@ -53,6 +62,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -98,9 +108,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -110,6 +120,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +316,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +326,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -348,6 +362,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch64_firefly_openamp_driver_core.config b/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch64_firefly_openamp_driver_core.config index 7424a2d7..bbd999d6 100644 --- a/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch64_firefly_openamp_driver_core.config +++ b/example/system/amp/openamp/driver_core/configs/phytiumpi_aarch64_firefly_openamp_driver_core.config @@ -33,6 +33,15 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=2 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -47,6 +56,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -92,9 +102,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -104,6 +114,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +305,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +315,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -337,6 +351,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/fig/1677585960509.png b/example/system/amp/openamp/driver_core/fig/1677585960509.png deleted file mode 100644 index 38ac275275e61d89fb31211a2b7cd2116b561935..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114715 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 diff --git a/example/system/amp/openamp/driver_core/fig/20230512192325.png b/example/system/amp/openamp/driver_core/fig/20230512192325.png deleted file mode 100644 index 683cdf3f2d2b2b50a7bf928ce6a3e6f7ec738209..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 257953 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%0AwK8Dq>LkCaUl1Eo?MX82i!VYe=b6WHw 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 VI7%_vyBS0>jU!DwTcJcCHa%j! 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 z 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 diff --git a/example/system/amp/openamp/driver_core/fig/20230512195526.png b/example/system/amp/openamp/driver_core/fig/20230512195526.png deleted file mode 100644 index bf31250f4ce2a60311d724dd61c4c17230e2c66b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 114642 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

EIu>yo{ZAn5nEi&E0XaED9n$L2-0Z6imnr>tMu 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�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

CiB$U zQQS%q%}kGc{&UZ8wlO<5GsQYiaKyl}Ri@q4ziO17bd|>P_8|_~C5G}{qVS!d>=(igg~SlnOiGrx-*TE=_19y zha^|)sHY$=en;@6=E;*07AEj)>D$!4zCV+k=Jv02S}r;!h=Z#*7c}Zt3tN_RYnguk z;75b}5~u$=soaAD??ONpkl|JmVNf!M)Hvk%@I7VE`mf9lj`d3sp^ggYk=J~Ngcah8 zF;L6_VQV(lfn^?K$6L%kt9~@<=i|ei;9HyFvOe}D`)vEwD^in_c*{h)#~4NJQ{z%E z#G-(pqCTiHd3zt!s-gP10|y?vu1w>gXQrF3y|<0f{Ymy0e?_Z0|1BH2d_|YKst6=gY}>WL zg0FKxXb3E!<(T6i#$99Bp@LNUG#>gxmt&*>wB6aB-jsIaoqpi*6WIyObT6<~9T z;w;06*`EfMzV?ApL#!Xz4l>kVldz15?G>2+etyx*LFB{FQSax04oNLl0Tn*Yn525v zMnXqq_3&#VccCK88}W5;LWGe*L*|OZJvrqENy2woQU|GC38gWl&+m}P{;@7r5cBLTmh zA*`j-I#9Aj3=+i>83oOlFMVQm350Drnf~RkI1FVpgtDc)tWHTh1Ky~>>~J%?E04!M z{_RN`EA~tbaJ(P!Q)wi}HkVH~hes+QN6Q8dt2Rt3IbK1mHqiKqn})J03ej2aK_uQ@ zaH4_pK>a%zw7Qt;{&w%%P~#e5%4M8W?zZ%Y#2Q|zth!xu8jZdzLbBdA{CD)2wibu! zm~}?zmz;hbD>gQWOpM1G959I3okpXOVzed(sUqVrmBsi*qLBb#kJmp4mmVECnH zxPykZ*6wP&X$qvN{YlGH|Bb)hAV)cA*zF8y-m*R(6AfXRDj*C;MP&@rY#(jx5#CQa zQ0~h!{lPx$er-fXLE^{Wz+mU6db516+R%TczjGz|%F9Kg;eaEu4z2G9}ao03mI5&LDmsooo91y7&OxN&>1Lsmvx& z(7&ZWAH&DjjvEzGEku;e7%V|q(y5-?GI1_ROE|lTLBc2N!wgycWoMc1LsX_DSB<2Z zg$-vspd#cxU3B6A&KzaPv})9l(V5Vt|5~(%wmMqC1HuolQjq#@9)!mgB*>3 zxO&w?ku`ETZCrr^eA@pIw1`yEeWB70)2aoXDzl^VM@?=<38qPTlDA&@`<#+6Jr&sg zgHU(35c{V!UK~m~ zv^jFja;znA_Hs9#mu5zh0a0$;`Pp(jmN7T)bX1tmLIkUp zWF9r4<6Qy6zk~ZwJBM>1;?4_VxU(N~e6CXG#dLA)wbSYD{~+;35ZIu>j~EdWR6J@nOji;wWd~^jglMJJ96=f3%;H-7 z)^v8%1M+YRMVWuCG@@9AkePkRC!8;8w#Qcwcx$M`#v7dINA?GDVCZi6X#peQIK|tm zrR5uoWjNlnKTPlGDUc*JxB#E-srU;?n&8BuOcW|2d9h&ND=)=YWt~W6B`x860FRc% zw1w*A(61ZZLKF#fNnyrwUk|{tMa6tta1EZgOeKnz19H+?S+JPgBwU7geUa}m5%{}% zgLOUGo?e?Nd>FlC<`N@rIuAlHVgNfSbheG^50+w4q7E63+i?OFo0?A>q{ooknVYM& zhs(*>xGb{ZpO=0G(5&L24L&WiTH(X}dwe-Q39eEEKe+mpyAut3PA+xZ^RhxE*BOeAA`qL=VL{F$*2lHTbwXlQ%s3cG+R6Gebmo# z0nhk874Q7{`a2?A;ezRv?x2-oS&HoGP7CfNadJ*wj_g>)HAPF47ze2WzKdK5Dvxt@ zr_{jUZqEh!G}X%r)0VI49{A`nWY<#(3KWUFlk%SiJ$08+f}8}3?8%yBo8~n$gZn8@ zw;O@L9;wC61f|t5_rsT$BB%OnPSoZ|-_5SNv{f_R=`pv;@0Q47pAFy_L^uXzqP=?O zZi~-54o^7ow2vL749D&K(m=nzG({meKjq2Lppd^sGXN|;4W>BW59zMd+45%u$^%$A zG7KFTHAyEm>khegu}2F5e)|%TqvMA6J0##Jb;;{ZKUA<>5;3=F(c^tRxpL0eG5I!d zQ=+t89bqC8H6qmOZq2rjS#+NMFmCkyIMC7iI03UIx0>)D1W<@PzFVM!8w{as6&^26 zAcwYD>7f%r_rWWipks=m*`1Y6ssTLnO-1~Td`8<*Pw`b{GxDof*W0~{^jYP_@AWiJ zQHvu@U6L~#T_E;^<{x7ac@ZL~#81T2C4LR{{qp{%vP@Qw$gWUIlbyy$$cQ!KfKME} zW(TFNUzogBXnFL2$!FIX;)s!}zBrWfpRRE~Y9z`H>9cEebp#NTsEM})Lkq1Zl(@R- z8(yG}X4u=+N+RXv-h7N!nCv~8?>?@z9aq{P5mUBsA+gOQH*)bGmMqP-D+<}|#w%Hr z%A?lNAE;2b1S5W-o{KZOSYO_Ke=|VP`5Z5{=gIwVFYo{Bq_LK+o9}k`UF$u2O@$uE zfWAeudz~aEH>K64;JDyGO3d3rr_UwUa)7SsS7Y`b?nm{@Z+w}SWX9s5mHV6<-vQI6 zH^a6l<3A5fZgrkaaLss|qdj!ypC0%QN-V({`kaD|E3(sH`u`w$E%o4JSX+upR(wC=M|wQCD8>q^5`*QE%u4$?jYw^$Z~^@-aK~2o zrr7L=k|dLjK8fOCIQ0*)kz^@`gIocQGM#0O`Hq45iGmv%_*`#GbxFt#RCB|;Rh#s@ zbCXAAj(zfFPau`6PpvdiaR64!Zk#-LQWe_K=;|##XDq6 z1Gsguf&{vgjnR%%B8DX&Z?7LYg*=vj+Ch2uNG7#VRCsaRlzNA2Xqr;=CrJ?;K&}AXlOYW|wtMG;%HL*IdNE4(003D}tiu@Xo@?{r!I|4ZSmenA|1llz8B#K*S!f4*u@LI6N z=BidbXQX3f07I!-IM#F53#Ug|v}o)u{*?0sqD3KvB>jab37r_hwW@kzK&D}bcwTG8 zz24U+nAFknOvzeWUDBsfDM^kPKP!3&{%Uvb0jSsjHesCMue}*j|Yz>z1>WW|0d-LuNR6tUr3R zL-7Os*8#^JLzE74U7Ic5Cn?zWzJC6b+SlXS|FV+%(pF7jB7hD1Yh?{a*^JOocOdP~ z_78J#ANv5qa813S3<+OY5wwWmOjc$SjwyA7h|i@H zN;#w1T+>D~bP9x>_iOc?GtQqb8BuGx#qo-6B)O`WvE;^VcPA-Qivm_tOypM5@YDrk zgT1sEgb>`JQJ#j|J zK4%-yj(Drt??SFEx2f8wwC1N4JT6|U>905p2^${7+W8^}eE1=quKkjdUZw9?Nf>wo z9xNRd;r0KHi0sOh+$)M7H0?9|gblxjFFWt6(qO+Q-!;<=v*T&G&HM*6Xfqi|uZ3G+ zL>{P$P>UQF*Tg=q*(G4 zRtQ2kI#VLZ6z;fW+vdmA~kex^yyM{004?!qkg)Oje5axbQi+4(q&&I zB=BsD(pquTh4&$2y1;4Kn+4u*`(glA*>xLD&>R)C$~B>ZshXY?QV~^Yu6i~C2J_vv zGFkHNHG#9IAjf59&4Cx)x`W{q@~~!^aJRNouzjubELFoyTeOryRcs}K)=0i;vRaB; zN?{^bpLEmhA?@DMhadWrKiHN15bTi9+Q-#P+m;ICrp|tP zrm}gl0cUdD@U$4q_|ceNS{|mD4on)oY<3h7P33c!yb*B6u0-J~N5=wZ?ae%2qCB=d zKRL;m{ou>2Ids^-{k)ir<;|?=nxj{P$;2Nwl_EVgI)xU-1rtv zjF8+y`$0jWp-eatGhv<)dpVM7ce%n$d7TDL_4$JoU<2zmFuzL?=zwfr$1tPJ9F`{N zAsW&&$7+;V9Z-MN5EN;(->787-XNI+|DI#Hr~4*M=unI`Md<~do=4DF{l>L+?OWJ6 z?()ix&Kwm(R5GT|)}~5ihkdP#(C_ien!=7vX96lvxBHG)s!hzk%Qy88g3!i*DKYd7 zTb8a_r^dHH1Y9xK8LFXfa=Em$^7nTO zE36Djpp_d$SZK*g$z5Jq)~!;gxzfHuOC;3z<||_!gteyqZ9&B>9X)IETaK)~xm;Jy zQTv7xY(d0$zv+0f0lTv>@#OVJWo5$&=w?3wKOfJ-zRao9gQ0a4s3erT;g++|LnQA^ zpoF&d%Zq3-+q1=0?#zXzT;L2azi0h+Y&;FSv~j}`f>C@d7D6YX&29daiC z^SE>)zd7*?)6~377pi%3J#ORhFel1#dH2`N013{2f|IEueFB{l1tN1Ev5y<${mIO+ z_?0WEhxTGY^30Sqc*)l4jdbc4Vp~)+vxC~vmScL5bnn9$iB>u={jXv^7lu;18&)(0 zBns5BEu%aq*Et|~MecAP%jI;3=reK|4K;@qJkIjN;g`S`fa-52JW77pzvqzLuD@U` zNrJ^ugqgAF#$>A=NGb$&(Mgt;iC}OW8^pU6<);q_>gpt zh4=B$wYIh!{48M%W7w<7BccYE;^+@881VsHLba5!oUx+5mMdnSNQIb0*?K`9R3 zUv1oT&{LDlx6;`*D2Lr3_;u&jQQeq!l$~m#!0ULoux7$SHL~|Wx08^?Kqw~qHS_z+ zbpMy2^0V@oy4wpLU)L+hvQ z@3px*jTE@$q9*wAau2_=8A+)~W23cAmxTNRgeZp*T?Y*a!b=L!ZjkZPXN&MPGv6|j zhR0lW@2sU26Gq-U)x6KdxzuFmfOcRFmT1(Xa{{U?o9ja4>e)&87;aU54teXovY;Ld zh+oji#7!ZF?V_f^yS$SPIZ_b;KAXWSrjw3>pF=R^^N{LP`0ftZ>#by4Ys75 zxpjc*uFsT$ z!0OoCCj5DTT8Z{^5y6gNciQ-W;q9zr;tHTWO^X$GcXxNU;#OpEcX#(fad(H}FgSy2 zac7D<6n7{xICOdMug&gz$tJtm`D2oq+?nJilXLH!bAI2KN=J~}>92jR0?ZG7tGoZg zFulbJvt!}{q-ccBlvJsbDnJVUF>7Rqv7TcaFZjhE;X10*RST_X)^@TR=gA2Ea&d zk~p#jqN8F?o+QCtdJLTjbMCM?$&)T|a}Mt@$s7fhr7}T>eRD2_dqbY^2iXH)-ZG=@ zecIgX#zQ;nSaoX`&l+YY8rMHatfB1A5<0iU_!d76t=$D|kZX#fQq+aIV#H~0R;smF zhZE-P80kc+4U#f14GvV`6ITXbHqWI0&USU)p05j7q4dzP|MP@>R(-ayoXe*4D!))+ zk_9~Wip0~qG&nfEy*n7jQ;R~T)uc_61l=5q?-mgO6h!Ax;vsf)s zsZygFxdpa^M|=Awoo@&C#RktGl5B4BdUGX(E0%}bk}`rAI#8|hAl^6k38(^0q!P`q zu}&x3i2|fr;1~fSY>Yu=9Gs=NvWfYXUrD&9jUVl-`E!%ib>U1VxY$CCxww`_)&=+x zxpO>^@Ym3u>hFNb+KO7c&+V24K1_GmP**_MKXRI`%J}tbdH2`7xl%BFBNOChve~~z zw!&?PpFar`POBu#HLUb4SEDHtw!2HOqOR&-bxqHP$qVcxnMfWk8;0^n{5To;ZLWZC zt>BSmZ}{=FY+z2fhd;s*_W?lY zs=XG*p3W8Fwzmck-UKMxsMhk$8=0ql@Ng9~x`VoooMeqT1{IT<{1Qp@&iCm8_~Mt` zt1RC>F*X+25iUkM(^-wyBdBtYgxVIGPtbukX)=P5pjj_sYXAjnj;XDlel%bF1|MF} z3e-*)73~qt;c;bfVoAcQ&(x$U8k);ShPZh}7S$=5biIF+PZlrrKmRb^Q)d+LS$6Sh z>-oCY;nUzai@3|j<8z|&80F}Qe#;l)Y<+m|D4;oc8e^aXV2ZOGj>!(U3FnOBdNDdM zDKfol1G_?kBLkd3V%8it7zDv=^81E9`sk}O_D`snQb`V8d-gdw)%E*b)qA?V8ua^v zN(+11Dk5AKs8bgkT}_!LQw4S%=1~-10OABcLD~Qu8LLh;51&PMYbHexrbdWLviac; z_aFBkphu-VE2onS<3>TC=Rc_Xt`+hMKA(21@b3ea5kshk2!gel7g$PoMHATfqKd!s zJZ9u3a+1lHIJ4FTvZc#80m)Hz+&zrtm%~*$uKZ_5gxpNo%KYx*t)tSUJN=)iRnc#@ zgZzKhE}T6V2iw99c}hCo^zmi?Y8NQq+G701JILNkA&qk&12kP1>Dv% z??c(j7o~m=eviZCt&igeD%jqkj|zk(g7B%L@)9T9rv)n{n~l!vpAsq;b)TJwk0$Id znYoXUU9}FE1QJ`o=HdPs2;_D^mR3$rdtE_XpEg458bh3#$3)+!ONK{yOplQxXL@s1 ztBn^^w$WA*;`ENo;6lG+lu;5ks*-*E#w^yfShEacZpSLewrMpxj}&3l?%IT2vJmnO zNtcOAw3MO(i~Azzk94{fGa&_KuWs`rc#*b3A`X1Rp}(StSlFgC5YDTfu`< z@MxlhWn+lvz{8#m&m~EfYT5Uzd}U&4b-9jVUhvd8nKcwRIe~f%VbupzYi#kAE37VU zY);}`Bs5QJQT~HcL=>VQ9aT|_9&a+^?mwei{2NIN+}qyr&n|pre7tw!chy**4x||! zxA;oPt`Pm279^G3OdI9e*tyPXoaXj)J*9C{dcoVOza$wc^1W*#kxFaCF7gfMnPZ#* zj;aN|v2ozRc9ygiZSzOoWIcbrE7HMM@@&IQ;R?Yz>l8obgS`+HTO5JrS{JxeZ@Fef zoeghb=m%U~ui~as#vFe|$7c@Q2$-&6D4#n9Kg|g~R)B&Qb8^J)SU~JAY?kRHbQvAo zgG+8T2bG;#Wa-@tUhfqbX?!`*&%e^7Jz^rK?P75zfAk<=L%%y)-FU($_=I>b-{XBA zB5g_Qcm}`iw3Yjk3~oCR=?uh9+6pJu+e}XFh4d}7QeyA%QV0kv1Uq8`pkSc@Jwfpn z$1NoGIFpikBi1f8qXG?!s_irlRG$OVEDejpGoA%rs@=KGhUU@5!ZdJ4^oonfX<

` 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

Bz=2PSN^sh9)yFD!QH;?JS zZM6$fz1|GBb4tiQ`%#StellYL)HZzI?oO7IgR?%W_)8;A8aUh|l2wsEZTUtLJ;!RG z6xR;CuL=zwgxUpF8|Hn*nS$B978%}-V6RI)?XDVLa&Pn#s=lmFV{v>eLbcZ5s#yX& z(MxS5G$_|QFVkSGxO`lBup(X0yjaSOb{KVlhIqA<@VS)CR~B{Y_@Y~lO6*fD3 z5`#n-7RW6x#Q7&l;~IyW#hGUKr=kcYG2^(F4GqESbvvD(`O!QTF{Xv+ap_|5#Ndc) zq5&FQv_dVMJfedMf?}WE_gDTxIWb-pKD^DQs$Q!s1rc1Ln#e|_rF4;W+ht8t?p8t9;ov;(`Xp-G<8Dg>_*;`^K@SE}lD8iVS4e8Ah9PDO!^)a&Hk>BopT@;QJFQ~TQH&NZa zm5sh|A&0cd7d!4!c{=AV<&oYq?Y^FZUi)jlbmamp@Qdn(6l>E3 zp3d8tRo0f>67=gG>RT2)62C#iet3hHzi!Jc8WCjVOOjlA%?0rgDRKL$yzE>79{q=7 zok1%6vM6ME`bf;3k)(ZMck)6%ti}MT#+$>$q#TD4(u`5C7=0sL-xP(0KrAz8ARu`om;6|SVm2XQS zF-r5krPr20$&D$my{j)MXhs(8KWt!>QepN^_Zq^*P#<8wvxa*0$v?8>1~R=n&z)Y^ z%!IIgQiA*iQl@LO#p;qBt>JJGs+uC^Ji1*}0DtS9<&)#i&kiLQ-1!{baso9Ei5wI_ z6$66!W3~TMjJ*+^Wh+`03zekR1?rJ1c0ra+0Hw%In3nZ1jEXWv54Dz!DGEu6dui=; zUg>el@jQdyiHx0YSuyH7Nq_Q2%`mLuADv99S$3{WUeOtgm%$%oBIZN^gde#7+J99r z$s3e`FQfe4Z+8WF6Ml311>d0D1kiB)?`zb*c~B75{Rf6C-5SN?Cx1}l_uh*AH;CS9 zhY|hX9)30t6y+6EaG8$u>zV+Z|L8LkaP)}ajghNw{O}8SlOpMY9fvS_ zA$T`;77*bpYr)hxT88eusi;*1_9b$7)F>GqjD8K13lVL~HfJN>zI5J!whx*Thd=Ca zV@o1Se#YBD+*W{7s9EKc`y2P3ud-{|n87~Au$>sR*Y3uKq+g4|#VCK$c_}oY8(OQV zjMfcwH}Zhdz%NLM9~RF4zr{nWWLffF=Cqcsv zVwQ1pD*=BIJLLu6jBh`@&bXt#+|aFH0y%aqS10MTe6??{Wv!19Ptup`(b^2m?@bK>_R31NPj%}N&jvk?-NCk1aH&2J({0UG)GJhO1w;hP@(ABZ%wp}YZ3(C_{ z8ZH>0g3usI)K+C%^qB%=M!I@xHwYZpqm1r;V5j{kb@ZmRpsR#A`a<3ad366n45=kipQLk)?Pfg6lSEO>!$c& zWfS6P0Nx2G;l5Uq#}#^4Y@6;FUL(+*r6bo6tZ8q$;xwwfHWU9JN)q6p(P?yF&X#~m zIeZ`eLfDekAXKB9xzFg3tliu)d{^TUW%&jKY$^e80VW#8N86-~*GLsW1zB8+ZVtET zymKq(cZ`xG{>cYzQ4<^wn!@%C2y#&)4(VF^#$HP&L3_>trtu7E-Y&r6P0Q8kugjG` ztrD*imzxqCd8h{GH{Z$Ir%}oZv=p|EY{qLfu+om5pPtrOyn7HIr)QSOU|J`8kPsX& z&mkeD3RhtX3vhFnHWPxixl~b^(XDY*I`{D`w~>)8Qc7*q+~*lUUuCoxG`2XbA_E(L zt%z0JF<%E5cv{ncYNh=1+1FPXSIT74S67$w!L!xbLHnm3DV>dQ@7|B}G%THb3(Cpf zI)(-HUYTKkc+|nL6K_vh(g(VXu+)pmOm3$9Ek>`ZOF;*f)H!doS|_)6BJ-;7%5=^@ zVsHD6k$T(8)^Fk~c^rS{&ze?0Fkn^L_Y$9)$SZke*9 zo8d=8Gk$-6WTwD_<6_9VUhhbD!6SZJqeQiS4``y35qydTKfVr8=#U>^asx34DB{?+ z1#~-D;Exua(Dw((lixrOS7F+)zrJo;{e6zO;Wu-Y?8 zXEC7rJR30kK$2y<@RY-^L_n6j7x|LIaU)^=*l z6xkj|n&NK`z9C+6pULBdvv5a8NpXF76B8{J9)`?RjdS|Y{f!~8yp)UUzP9^6l=cPJ zZH2Wz<28&G)-@N)cq047i78z{8Zu*S6)n&W3MW36rG}n`r2;#7%u{}fCPcrokzM+7 z_7lr=I1kr8oO-@^$*%)ap3Bx^!lPgsSH14H5^}XEAC^0~N>6;ob$XiR% zs8&iVa%Vw!^a88;RNfoq_D&kXNbm-u|Cah!#|=`;Z*PWzve6iJVTi=Rh@#55j9&g& zpdy2K)*$smH8?D75B)e2m<1OU6wLEtlV_Nt>J{&N9V*FP-$%fXA?CwdUCy1h#V&+$ zzur!Da$rh32?BYhftJ^n&Dr(CGgTVp=Fv`35Q^N(*@B6)cD7g{XxV!ns}4e#F?o_+ z)6xD+BQ;ikYpGTYH-#rpBl8Mm;ScNzRIf#uYUJBGq=WgbraHLvx`69gs}Zgt(@syu^0DMdNu4`hoE1x_w9vV^ab zHAnroR{-8D>K(HL;eIxIZNP!rPGc$?%KAUPN~zS@cByzINM2dZcm9?Q61dVQzcF8* zzq3@|H?}EAuYiXAYB!6JK+^!J3pkAfcwftn<1bcChV6sCywD@3=VWXQbB8;5=IJ#O znvb-f2bcalu2X9|y4wB;X^PNF42jqQoURj_Mob+#Fg`Hx1o;Q}xovei3u%S|yjM=v z_v@7M%eBoOUL~?HqeJ#-(2h1tI~x9kUY~&>?jj;->L8%;SrHrY-mPI~!==VL=4N&0 zAbX~EelPZ)eV)Re9P;p2c&pP5Gn~5$0oS%`=I((BzA6y*%8}ZuSXB>bfcBBXsp-@v z`;Cgzp?`GIL2^F$JW>(grn$jiXeWAfvxq_|{#|sxzEY?Pc78)Ahr;B&zrNk=?J!2k z$0hPbuZDZoRG*PYX44iX|CZCEy$t(2N0Ez|u<<{gzstk@EJC><|BlW z&Ej5BuWTu>Vsi^unofI4(>~7fZSb~Fub481sd(EidIw!FlCG_+fz8fb8(NlHe6;3G zvtWB)`C&iJezbfPUp1c`N-P?5y&n6PQIo~?mP*rrOd<5xW1DoaxR-Z@zHpMiOl)R*MLVV0r!+2|{^ilsd-Qt!Qbac8ZT28b zZK4ngE3S}Tl#R!DqWStns>e_rE7I2=tZrMfH_b)iYak{HE>&)nSb=8x;J*>&u|j^7 zC#w@LoL=gjJ3TY)nj@ZX#?{k)Dkky?t^O&+S&8hzk{#O0jey$)@mMb<5=kuSey`d3 zaC)-1EmvY;u#u-vR)9dP$Rl+eF~?MxAH-{zj-=%N>c2)~HHgx84Pt5%6T%yFj4~OG z@Sgv+pFmE{Q!xBG^ARYreR2Be-n441Y44-guW_2EU|54!5dNsGidR&?gU?|Sy)gGr z0xDhRQNuYvc`}zT9j^Bj%VGjq($%uI=y z8DfsviDT#0x$pIp&i9?$>ef5byWQ$PrKP=9wM$ED&oL&AnYV&BgkJ1TKjjvfyr~}_ zU(%j2um)CAuX7W#^c2?!UnO#DQIDC*w%EzSSvNAPDWfu`GHhA34US$_jO`4o{mIk| z_ii!XM#-+%kU55@8AM{+Wa^s=oePgJ2ho|N^blvDYNL;WhLCm<1R9%&H9eh0IR{$+ z-Vq6;r4dL@6LbY074d!s6~JRQOWPVD%P|UW_5hJe^NAq(p)`+>U^(T!<}+&fN;H|V9=R!& zd-mELf>k_I=5~hLi+x4GsECSqf$e3~aQlN87N}R$D0MXxbQ$7f-e2|_#wSmDY9hyq z%U%U{hy&4He40U`C-jOjggQD@-fn*Y2QA(4>1ml0{d~vuwe`i!vuJ6h?3Erq_fiYQ z!tq@u$k)`XZzCa9SEeuZnWiau(#4S8&PW!PY>GJE3T4d*dRR)>HMgT zb-7j4tu>muno6K$M!MxX%mF2qZr8vibZ6)vZKC)m(V4^Z8zV;PzD5}-zrQevx3ypT7q`2XWj5I7vwStX zRPb>L)W|MfeAJxgam34SOBiU`qQ4yLX#aFmEqvF=MW$VHdQbpvtTjIJorLgFZ}vDZ z*P^WH$kqquzH&)7IkC`k#O_!^b$PGX*sOGV=Nl}M72h)(??-&BB-^E&E(NwXw=_F( z1u~1S+0jNhU1J`D?Keb3>#Jj(ivi@`-(9vubsc)wNG<7oM*3VJ>Cm8v<#X0n*IPhR9@nPtKi3Qco2VJfcJA_%_v_xbnjU^LGg(x znYccCSU6`YHFC^$H+Ic3)i6`_qPpBgfm=

?N`3b(E@Xr2Ccs9*JpUcJ((j@xZ!2F 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 b%r;2`81L#SY6(*_dCTqt|EOHS=(&FbboN<& diff --git a/example/system/amp/openamp/driver_core/fig/e2000_aarch64_openamp_startup.png b/example/system/amp/openamp/driver_core/fig/e2000_aarch64_openamp_startup.png index ece3508b32dd54a48b4d98832cec77edff4549c6..f4ca99edc5a301f64157d4840490b1a58961c476 100644 GIT binary patch literal 136696 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 literal 242426 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 z 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 diff --git a/example/system/amp/openamp/driver_core/fig/openamp32.png b/example/system/amp/openamp/driver_core/fig/openamp32.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c0136fb2ec1561b664477b3652839a47febd61 GIT binary patch literal 85046 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%0DK5ZE?gOzCPA; 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 literal 0 HcmV?d00001 diff --git a/example/system/amp/openamp/driver_core/fig/openamp64.png b/example/system/amp/openamp/driver_core/fig/openamp64.png new file mode 100644 index 0000000000000000000000000000000000000000..7657764ff6d1f05655d15c9db35a7db069210957 GIT binary patch literal 84465 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 Ai~s-t literal 0 HcmV?d00001 diff --git a/example/system/amp/openamp/driver_core/fig/openamp64_auto.png b/example/system/amp/openamp/driver_core/fig/openamp64_auto.png new file mode 100644 index 0000000000000000000000000000000000000000..7a2fe99b856bd9a6d524b1022d14846d85696bcf GIT binary patch literal 226121 zcmeEvd0bUx{{LZhmr-&BK}VDN;zD8|%3@#Bv{9+AGj3So5||q*E+E3aXz7qCHfTvG zm^Ru>k|>HB$~84ag^O7#E`S?gqM{IjEcf^RJkL3IJqK%MzQ5P6`ORM$aL+yGInVN0 z-b>tDW8Y}gvTI905Za6y`TG9|g6&2@u+C|2kDuI{9XTHVu?v|weAxf=O1LfD{d#($ zV6#X!>h;(D7-4ny)QtTvhF(?Qtc(15cIB1Q{qs&`czTYq&$*H@?^;H?kEdS?x#ka6p^ zq4V$QTzwbc4{7VO++Hxbig>|t)mEzoiRT(Gzf$4RDg7@OuL&B{Z{vU0u*VZ0FVG!X zGylf<9&czB{z?@rOexu?d#|)%>U5Bt*>LEhnKE_f<@WeWewb~X;-uekdh zYlHi={L%uQn>`-CE^uXP{ZDJNZuXs8-zG3S=y-&ugO$ULBZ}jJ8{d;9udhMMH>l7ZgBfGz4 zSHtfI)Yhl&5X!?G8g8dd@e$--ZdM{)e#&zuN)ekV{UXXPiu{_Mbg}HQ17;LY>lgCku7e7rI+af+t;>-mo@<=_l;-)j>?@}}ZwB+}G@ow6

>hl5;gi!vZ{6=3 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 z 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 G`hNh}Y!vbU literal 0 HcmV?d00001 diff --git a/example/system/amp/openamp/driver_core/sdkconfig b/example/system/amp/openamp/driver_core/sdkconfig index 7424a2d7..589235d2 100644 --- a/example/system/amp/openamp/driver_core/sdkconfig +++ b/example/system/amp/openamp/driver_core/sdkconfig @@ -33,6 +33,15 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration +# +# multi-core system deployment framework +# +CONFIG_USE_MSDF=y +CONFIG_MSDF0=y +# CONFIG_MSDF1 is not set +CONFIG_MSDF_CORE_ID=2 +# end of multi-core system deployment framework + CONFIG_MMU_PAGE_SIZE=0x1000 CONFIG_MAX_XLAT_TABLES=256 # end of Arch configuration @@ -40,14 +49,16 @@ CONFIG_MAX_XLAT_TABLES=256 # # Soc configuration # -CONFIG_TARGET_PHYTIUMPI=y -# CONFIG_TARGET_E2000Q is not set +# CONFIG_TARGET_PHYTIUMPI is not set +CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_E2000D is not set # CONFIG_TARGET_E2000S is not set # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set -CONFIG_SOC_NAME="phytiumpi" +# CONFIG_TARGET_QEMU_VIRT is not set +CONFIG_SOC_NAME="e2000" +CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 CONFIG_F32BIT_MEMORY_LENGTH=0x80000000 @@ -62,7 +73,7 @@ CONFIG_DEFAULT_DEBUG_PRINT_UART1=y # # Board Configuration # -CONFIG_BOARD_NAME="firefly" +CONFIG_BOARD_NAME="demo" # CONFIG_USE_SPI_IOPAD is not set # CONFIG_USE_GPIO_IOPAD is not set # CONFIG_USE_CAN_IOPAD is not set @@ -72,7 +83,7 @@ CONFIG_BOARD_NAME="firefly" # CONFIG_USE_TACHO_IOPAD is not set # CONFIG_USE_UART_IOPAD is not set # CONFIG_USE_THIRD_PARTY_IOPAD is not set -CONFIG_FIREFLY_DEMO_BOARD=y +CONFIG_E2000Q_DEMO_BOARD=y # # IO mux configuration when board start up @@ -92,9 +103,9 @@ CONFIG_TARGET_NAME="openamp_driver_core" # Sdk common configuration # CONFIG_ELOG_LINE_BUF_SIZE=0x100 -CONFIG_LOG_VERBOS=y +# CONFIG_LOG_VERBOS is not set # CONFIG_LOG_DEBUG is not set -# CONFIG_LOG_INFO is not set +CONFIG_LOG_INFO=y # CONFIG_LOG_WARN is not set # CONFIG_LOG_ERROR is not set # CONFIG_LOG_NONE is not set @@ -104,6 +115,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +306,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +316,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -337,6 +352,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp/driver_core/sdkconfig.h b/example/system/amp/openamp/driver_core/sdkconfig.h index f42d8a10..b84bdc5c 100644 --- a/example/system/amp/openamp/driver_core/sdkconfig.h +++ b/example/system/amp/openamp/driver_core/sdkconfig.h @@ -31,20 +31,30 @@ /* CONFIG_BOOT_WITH_FLUSH_CACHE is not set */ /* CONFIG_MMU_DEBUG_PRINTS is not set */ /* end of Arm architecture configuration */ + +/* multi-core system deployment framework */ + +#define CONFIG_USE_MSDF +#define CONFIG_MSDF0 +/* CONFIG_MSDF1 is not set */ +#define CONFIG_MSDF_CORE_ID 2 +/* end of multi-core system deployment framework */ #define CONFIG_MMU_PAGE_SIZE 0x1000 #define CONFIG_MAX_XLAT_TABLES 256 /* end of Arch configuration */ /* Soc configuration */ -#define CONFIG_TARGET_PHYTIUMPI -/* CONFIG_TARGET_E2000Q is not set */ +/* CONFIG_TARGET_PHYTIUMPI is not set */ +#define CONFIG_TARGET_E2000Q /* CONFIG_TARGET_E2000D is not set */ /* CONFIG_TARGET_E2000S is not set */ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ -#define CONFIG_SOC_NAME "phytiumpi" +/* CONFIG_TARGET_QEMU_VIRT is not set */ +#define CONFIG_SOC_NAME "e2000" +#define CONFIG_TARGET_TYPE_NAME "q" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 #define CONFIG_F32BIT_MEMORY_LENGTH 0x80000000 @@ -58,7 +68,7 @@ /* Board Configuration */ -#define CONFIG_BOARD_NAME "firefly" +#define CONFIG_BOARD_NAME "demo" /* CONFIG_USE_SPI_IOPAD is not set */ /* CONFIG_USE_GPIO_IOPAD is not set */ /* CONFIG_USE_CAN_IOPAD is not set */ @@ -68,7 +78,7 @@ /* CONFIG_USE_TACHO_IOPAD is not set */ /* CONFIG_USE_UART_IOPAD is not set */ /* CONFIG_USE_THIRD_PARTY_IOPAD is not set */ -#define CONFIG_FIREFLY_DEMO_BOARD +#define CONFIG_E2000Q_DEMO_BOARD /* IO mux configuration when board start up */ @@ -84,9 +94,9 @@ /* Sdk common configuration */ #define CONFIG_ELOG_LINE_BUF_SIZE 0x100 -#define CONFIG_LOG_VERBOS +/* CONFIG_LOG_VERBOS is not set */ /* CONFIG_LOG_DEBUG is not set */ -/* CONFIG_LOG_INFO is not set */ +#define CONFIG_LOG_INFO /* CONFIG_LOG_WARN is not set */ /* CONFIG_LOG_ERROR is not set */ /* CONFIG_LOG_NONE is not set */ @@ -96,6 +106,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +271,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +280,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ #define CONFIG_USE_AMP #define CONFIG_USE_LIBMETAL @@ -298,6 +312,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/system/amp/openamp_for_linux/configs/d2000_aarch32_test_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/d2000_aarch32_test_openamp_for_linux.config index 728eb581..e002ca12 100644 --- a/example/system/amp/openamp_for_linux/configs/d2000_aarch32_test_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/d2000_aarch32_test_openamp_for_linux.config @@ -49,6 +49,7 @@ CONFIG_ARM_MFLOAT_ABI="hard" # end of Compiler configuration CONFIG_USE_L3CACHE=y +# CONFIG_DISABLE_L3CACHE is not set CONFIG_USE_AARCH64_L1_TO_AARCH32=y # end of Arm architecture configuration @@ -66,6 +67,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +112,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -348,6 +354,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/d2000_aarch64_test_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/d2000_aarch64_test_openamp_for_linux.config index 6d35a91a..c3616af0 100644 --- a/example/system/amp/openamp_for_linux/configs/d2000_aarch64_test_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/d2000_aarch64_test_openamp_for_linux.config @@ -42,6 +42,7 @@ CONFIG_GCC_CODE_MODEL_SMALL=y # end of Compiler configuration CONFIG_USE_L3CACHE=y +# CONFIG_DISABLE_L3CACHE is not set CONFIG_BOOT_WITH_FLUSH_CACHE=y # CONFIG_MMU_DEBUG_PRINTS is not set # end of Arm architecture configuration @@ -60,6 +61,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +106,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration CONFIG_USE_AMP=y @@ -337,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/e2000d_aarch32_demo_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/e2000d_aarch32_demo_openamp_for_linux.config index 76ddadfe..00896c35 100644 --- a/example/system/amp/openamp_for_linux/configs/e2000d_aarch32_demo_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/e2000d_aarch32_demo_openamp_for_linux.config @@ -65,6 +65,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -123,6 +124,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -318,6 +320,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -351,6 +354,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/e2000d_aarch64_demo_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/e2000d_aarch64_demo_openamp_for_linux.config index 7e36a4fd..9cc5ab63 100644 --- a/example/system/amp/openamp_for_linux/configs/e2000d_aarch64_demo_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/e2000d_aarch64_demo_openamp_for_linux.config @@ -59,6 +59,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -117,6 +118,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -340,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/e2000q_aarch32_demo_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/e2000q_aarch32_demo_openamp_for_linux.config index 74a3be1e..0a8894e4 100644 --- a/example/system/amp/openamp_for_linux/configs/e2000q_aarch32_demo_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/e2000q_aarch32_demo_openamp_for_linux.config @@ -65,6 +65,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -122,6 +123,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -317,6 +319,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -350,6 +353,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/e2000q_aarch64_demo_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/e2000q_aarch64_demo_openamp_for_linux.config index fc3a1cd4..f3189862 100644 --- a/example/system/amp/openamp_for_linux/configs/e2000q_aarch64_demo_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/e2000q_aarch64_demo_openamp_for_linux.config @@ -59,6 +59,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -116,6 +117,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -339,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch32_firefly_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch32_firefly_openamp_for_linux.config index b313b29b..bf455e36 100644 --- a/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch32_firefly_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch32_firefly_openamp_for_linux.config @@ -65,6 +65,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -121,6 +122,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -316,6 +318,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -349,6 +352,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch64_firefly_openamp_for_linux.config b/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch64_firefly_openamp_for_linux.config index c0a9827f..0179b718 100644 --- a/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch64_firefly_openamp_for_linux.config +++ b/example/system/amp/openamp_for_linux/configs/phytiumpi_aarch64_firefly_openamp_for_linux.config @@ -59,6 +59,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -115,6 +116,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -338,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/sdkconfig b/example/system/amp/openamp_for_linux/sdkconfig index c0a9827f..0179b718 100644 --- a/example/system/amp/openamp_for_linux/sdkconfig +++ b/example/system/amp/openamp_for_linux/sdkconfig @@ -59,6 +59,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -115,6 +116,7 @@ CONFIG_LOG_DISPALY_CORE_NUM=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y # CONFIG_INTERRUPT_ROLE_MASTER is not set CONFIG_INTERRUPT_ROLE_SLAVE=y +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set # CONFIG_USE_LETTER_SHELL is not set CONFIG_USE_AMP=y CONFIG_USE_LIBMETAL=y @@ -338,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/amp/openamp_for_linux/sdkconfig.h b/example/system/amp/openamp_for_linux/sdkconfig.h index 920019b6..ac218029 100644 --- a/example/system/amp/openamp_for_linux/sdkconfig.h +++ b/example/system/amp/openamp_for_linux/sdkconfig.h @@ -51,6 +51,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -102,6 +103,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG /* CONFIG_INTERRUPT_ROLE_MASTER is not set */ #define CONFIG_INTERRUPT_ROLE_SLAVE +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -266,6 +268,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ /* CONFIG_USE_LETTER_SHELL is not set */ #define CONFIG_USE_AMP #define CONFIG_USE_LIBMETAL @@ -296,6 +299,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/system/atomic/configs/d2000_aarch32_test_atomic.config b/example/system/atomic/configs/d2000_aarch32_test_atomic.config index b332984c..e5abdf96 100644 --- a/example/system/atomic/configs/d2000_aarch32_test_atomic.config +++ b/example/system/atomic/configs/d2000_aarch32_test_atomic.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/d2000_aarch64_test_atomic.config b/example/system/atomic/configs/d2000_aarch64_test_atomic.config index ef039282..dfb2140b 100644 --- a/example/system/atomic/configs/d2000_aarch64_test_atomic.config +++ b/example/system/atomic/configs/d2000_aarch64_test_atomic.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/e2000d_aarch32_demo_atomic.config b/example/system/atomic/configs/e2000d_aarch32_demo_atomic.config index 91add3d9..5aef7fcd 100644 --- a/example/system/atomic/configs/e2000d_aarch32_demo_atomic.config +++ b/example/system/atomic/configs/e2000d_aarch32_demo_atomic.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/e2000d_aarch64_demo_atomic.config b/example/system/atomic/configs/e2000d_aarch64_demo_atomic.config index 47fa205c..ffe9085a 100644 --- a/example/system/atomic/configs/e2000d_aarch64_demo_atomic.config +++ b/example/system/atomic/configs/e2000d_aarch64_demo_atomic.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/e2000q_aarch32_demo_atomic.config b/example/system/atomic/configs/e2000q_aarch32_demo_atomic.config index 5b178f15..ae8bd5ef 100644 --- a/example/system/atomic/configs/e2000q_aarch32_demo_atomic.config +++ b/example/system/atomic/configs/e2000q_aarch32_demo_atomic.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/e2000q_aarch64_demo_atomic.config b/example/system/atomic/configs/e2000q_aarch64_demo_atomic.config index 20e15e13..73d87cdc 100644 --- a/example/system/atomic/configs/e2000q_aarch64_demo_atomic.config +++ b/example/system/atomic/configs/e2000q_aarch64_demo_atomic.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/ft2004_aarch32_dsk_atomic.config b/example/system/atomic/configs/ft2004_aarch32_dsk_atomic.config index 7ab3be54..ba6f80c5 100644 --- a/example/system/atomic/configs/ft2004_aarch32_dsk_atomic.config +++ b/example/system/atomic/configs/ft2004_aarch32_dsk_atomic.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/ft2004_aarch64_dsk_atomic.config b/example/system/atomic/configs/ft2004_aarch64_dsk_atomic.config index 90313de4..c8b84730 100644 --- a/example/system/atomic/configs/ft2004_aarch64_dsk_atomic.config +++ b/example/system/atomic/configs/ft2004_aarch64_dsk_atomic.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/phytiumpi_aarch32_firefly_atomic.config b/example/system/atomic/configs/phytiumpi_aarch32_firefly_atomic.config index 4699d7e3..f27e930a 100644 --- a/example/system/atomic/configs/phytiumpi_aarch32_firefly_atomic.config +++ b/example/system/atomic/configs/phytiumpi_aarch32_firefly_atomic.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/configs/phytiumpi_aarch64_firefly_atomic.config b/example/system/atomic/configs/phytiumpi_aarch64_firefly_atomic.config index 3a8bb2a0..a02ed21b 100644 --- a/example/system/atomic/configs/phytiumpi_aarch64_firefly_atomic.config +++ b/example/system/atomic/configs/phytiumpi_aarch64_firefly_atomic.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/sdkconfig b/example/system/atomic/sdkconfig index 3a8bb2a0..a02ed21b 100644 --- a/example/system/atomic/sdkconfig +++ b/example/system/atomic/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/atomic/sdkconfig.h b/example/system/atomic/sdkconfig.h index 055a9d68..155847e0 100644 --- a/example/system/atomic/sdkconfig.h +++ b/example/system/atomic/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/system/exception_debug/configs/d2000_aarch32_test_exception.config b/example/system/exception_debug/configs/d2000_aarch32_test_exception.config index 08fbfb18..324299b3 100644 --- a/example/system/exception_debug/configs/d2000_aarch32_test_exception.config +++ b/example/system/exception_debug/configs/d2000_aarch32_test_exception.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/d2000_aarch64_test_exception.config b/example/system/exception_debug/configs/d2000_aarch64_test_exception.config index 05fb1021..1e8f8247 100644 --- a/example/system/exception_debug/configs/d2000_aarch64_test_exception.config +++ b/example/system/exception_debug/configs/d2000_aarch64_test_exception.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/e2000d_aarch32_demo_exception.config b/example/system/exception_debug/configs/e2000d_aarch32_demo_exception.config index 7d9a4840..8a0cb558 100644 --- a/example/system/exception_debug/configs/e2000d_aarch32_demo_exception.config +++ b/example/system/exception_debug/configs/e2000d_aarch32_demo_exception.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/e2000d_aarch64_demo_exception.config b/example/system/exception_debug/configs/e2000d_aarch64_demo_exception.config index 698b25cd..da1acd09 100644 --- a/example/system/exception_debug/configs/e2000d_aarch64_demo_exception.config +++ b/example/system/exception_debug/configs/e2000d_aarch64_demo_exception.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/e2000q_aarch32_demo_exception.config b/example/system/exception_debug/configs/e2000q_aarch32_demo_exception.config index 4287be33..a9e60822 100644 --- a/example/system/exception_debug/configs/e2000q_aarch32_demo_exception.config +++ b/example/system/exception_debug/configs/e2000q_aarch32_demo_exception.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/e2000q_aarch64_demo_exception.config b/example/system/exception_debug/configs/e2000q_aarch64_demo_exception.config index 8c39c708..a3324391 100644 --- a/example/system/exception_debug/configs/e2000q_aarch64_demo_exception.config +++ b/example/system/exception_debug/configs/e2000q_aarch64_demo_exception.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/ft2004_aarch32_dsk_exception.config b/example/system/exception_debug/configs/ft2004_aarch32_dsk_exception.config index a7b2027e..dce07ce0 100644 --- a/example/system/exception_debug/configs/ft2004_aarch32_dsk_exception.config +++ b/example/system/exception_debug/configs/ft2004_aarch32_dsk_exception.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/ft2004_aarch64_dsk_exception.config b/example/system/exception_debug/configs/ft2004_aarch64_dsk_exception.config index 5cd69a2c..61c89fe1 100644 --- a/example/system/exception_debug/configs/ft2004_aarch64_dsk_exception.config +++ b/example/system/exception_debug/configs/ft2004_aarch64_dsk_exception.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/phytiumpi_aarch32_firefly_exception.config b/example/system/exception_debug/configs/phytiumpi_aarch32_firefly_exception.config index 29d26718..1a802516 100644 --- a/example/system/exception_debug/configs/phytiumpi_aarch32_firefly_exception.config +++ b/example/system/exception_debug/configs/phytiumpi_aarch32_firefly_exception.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/configs/phytiumpi_aarch64_firefly_exception.config b/example/system/exception_debug/configs/phytiumpi_aarch64_firefly_exception.config index fec85a7d..7e53da0b 100644 --- a/example/system/exception_debug/configs/phytiumpi_aarch64_firefly_exception.config +++ b/example/system/exception_debug/configs/phytiumpi_aarch64_firefly_exception.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/main.c b/example/system/exception_debug/main.c index ddea33a7..7c0af23f 100644 --- a/example/system/exception_debug/main.c +++ b/example/system/exception_debug/main.c @@ -26,21 +26,23 @@ #include "FreeRTOS.h" #include "task.h" #include "ftypes.h" +#include "sdkconfig.h" +#ifdef CONFIG_USE_LETTER_SHELL #include "shell.h" #include "shell_port.h" -#include "sdkconfig.h" +#endif int main() { printf("Exception debug func, FT Date: %s, Time: %s\n", __DATE__, __TIME__); BaseType_t xReturn = pdPASS; - +#ifdef CONFIG_USE_LETTER_SHELL xReturn = LSUserShellTask(); if (xReturn != pdPASS) { goto FAIL_EXIT; } - +#endif vTaskStartScheduler(); /* 启动任务,开启调度 */ while (1); /* 正常不会执行到这里 */ diff --git a/example/system/exception_debug/sdkconfig b/example/system/exception_debug/sdkconfig index fec85a7d..7e53da0b 100644 --- a/example/system/exception_debug/sdkconfig +++ b/example/system/exception_debug/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/exception_debug/sdkconfig.h b/example/system/exception_debug/sdkconfig.h index bbdb95a3..4a414252 100644 --- a/example/system/exception_debug/sdkconfig.h +++ b/example/system/exception_debug/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/system/exception_debug/src/exception_test.c b/example/system/exception_debug/src/exception_test.c index e0924605..dfd01725 100644 --- a/example/system/exception_debug/src/exception_test.c +++ b/example/system/exception_debug/src/exception_test.c @@ -26,8 +26,6 @@ #include "FreeRTOS.h" #include "task.h" #include "ftypes.h" -#include "shell.h" -#include "shell_port.h" #include "fmmu.h" #include "fio.h" #include "fkernel.h" diff --git a/example/system/nested_interrupt/configs/d2000_aarch32_test_nested_interrupt.config b/example/system/nested_interrupt/configs/d2000_aarch32_test_nested_interrupt.config index 8e74d092..370ae368 100644 --- a/example/system/nested_interrupt/configs/d2000_aarch32_test_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/d2000_aarch32_test_nested_interrupt.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/d2000_aarch64_test_nested_interrupt.config b/example/system/nested_interrupt/configs/d2000_aarch64_test_nested_interrupt.config index 7d2ebfd4..50f7a731 100644 --- a/example/system/nested_interrupt/configs/d2000_aarch64_test_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/d2000_aarch64_test_nested_interrupt.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/e2000d_aarch32_demo_nested_interrupt.config b/example/system/nested_interrupt/configs/e2000d_aarch32_demo_nested_interrupt.config index 0d9c870f..7c406ffb 100644 --- a/example/system/nested_interrupt/configs/e2000d_aarch32_demo_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/e2000d_aarch32_demo_nested_interrupt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/e2000d_aarch64_demo_nested_interrupt.config b/example/system/nested_interrupt/configs/e2000d_aarch64_demo_nested_interrupt.config index 842ea2d3..df091e98 100644 --- a/example/system/nested_interrupt/configs/e2000d_aarch64_demo_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/e2000d_aarch64_demo_nested_interrupt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/e2000q_aarch32_demo_nested_interrupt.config b/example/system/nested_interrupt/configs/e2000q_aarch32_demo_nested_interrupt.config index d29de091..8945e2b5 100644 --- a/example/system/nested_interrupt/configs/e2000q_aarch32_demo_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/e2000q_aarch32_demo_nested_interrupt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/e2000q_aarch64_demo_nested_interrupt.config b/example/system/nested_interrupt/configs/e2000q_aarch64_demo_nested_interrupt.config index aae5a4c3..c3e686f2 100644 --- a/example/system/nested_interrupt/configs/e2000q_aarch64_demo_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/e2000q_aarch64_demo_nested_interrupt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/ft2004_aarch32_dsk_nested_interrupt.config b/example/system/nested_interrupt/configs/ft2004_aarch32_dsk_nested_interrupt.config index 13b42c87..7344a3bd 100644 --- a/example/system/nested_interrupt/configs/ft2004_aarch32_dsk_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/ft2004_aarch32_dsk_nested_interrupt.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/ft2004_aarch64_dsk_nested_interrupt.config b/example/system/nested_interrupt/configs/ft2004_aarch64_dsk_nested_interrupt.config index 9cbc14ae..04aaa46c 100644 --- a/example/system/nested_interrupt/configs/ft2004_aarch64_dsk_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/ft2004_aarch64_dsk_nested_interrupt.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/phytiumpi_aarch32_firefly_nested_interrupt.config b/example/system/nested_interrupt/configs/phytiumpi_aarch32_firefly_nested_interrupt.config index 3bb78fa2..74883e5c 100644 --- a/example/system/nested_interrupt/configs/phytiumpi_aarch32_firefly_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/phytiumpi_aarch32_firefly_nested_interrupt.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/configs/phytiumpi_aarch64_firefly_nested_interrupt.config b/example/system/nested_interrupt/configs/phytiumpi_aarch64_firefly_nested_interrupt.config index 122b2756..ba0286c9 100644 --- a/example/system/nested_interrupt/configs/phytiumpi_aarch64_firefly_nested_interrupt.config +++ b/example/system/nested_interrupt/configs/phytiumpi_aarch64_firefly_nested_interrupt.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/sdkconfig b/example/system/nested_interrupt/sdkconfig index 122b2756..ba0286c9 100644 --- a/example/system/nested_interrupt/sdkconfig +++ b/example/system/nested_interrupt/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_INFO=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_BACKTRACE=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=12 diff --git a/example/system/nested_interrupt/sdkconfig.h b/example/system/nested_interrupt/sdkconfig.h index be79bfc6..a329beef 100644 --- a/example/system/nested_interrupt/sdkconfig.h +++ b/example/system/nested_interrupt/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 12 diff --git a/example/system/posix/configs/d2000_aarch32_test_posix.config b/example/system/posix/configs/d2000_aarch32_test_posix.config index 5dc3b9af..5cc92888 100644 --- a/example/system/posix/configs/d2000_aarch32_test_posix.config +++ b/example/system/posix/configs/d2000_aarch32_test_posix.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/d2000_aarch64_test_posix.config b/example/system/posix/configs/d2000_aarch64_test_posix.config index b435d242..755eb1a3 100644 --- a/example/system/posix/configs/d2000_aarch64_test_posix.config +++ b/example/system/posix/configs/d2000_aarch64_test_posix.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/e2000d_aarch32_demo_posix.config b/example/system/posix/configs/e2000d_aarch32_demo_posix.config index 2bf97f67..275d34b5 100644 --- a/example/system/posix/configs/e2000d_aarch32_demo_posix.config +++ b/example/system/posix/configs/e2000d_aarch32_demo_posix.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/e2000d_aarch64_demo_posix.config b/example/system/posix/configs/e2000d_aarch64_demo_posix.config index 202e764c..5acd32cb 100644 --- a/example/system/posix/configs/e2000d_aarch64_demo_posix.config +++ b/example/system/posix/configs/e2000d_aarch64_demo_posix.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/e2000q_aarch32_demo_posix.config b/example/system/posix/configs/e2000q_aarch32_demo_posix.config index 89873c71..1f67e751 100644 --- a/example/system/posix/configs/e2000q_aarch32_demo_posix.config +++ b/example/system/posix/configs/e2000q_aarch32_demo_posix.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/e2000q_aarch64_demo_posix.config b/example/system/posix/configs/e2000q_aarch64_demo_posix.config index 975b13fe..0a25eb6a 100644 --- a/example/system/posix/configs/e2000q_aarch64_demo_posix.config +++ b/example/system/posix/configs/e2000q_aarch64_demo_posix.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/ft2004_aarch32_dsk_posix.config b/example/system/posix/configs/ft2004_aarch32_dsk_posix.config index df473e0a..314a17ef 100644 --- a/example/system/posix/configs/ft2004_aarch32_dsk_posix.config +++ b/example/system/posix/configs/ft2004_aarch32_dsk_posix.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/ft2004_aarch64_dsk_posix.config b/example/system/posix/configs/ft2004_aarch64_dsk_posix.config index 1617e7b4..07a0765e 100644 --- a/example/system/posix/configs/ft2004_aarch64_dsk_posix.config +++ b/example/system/posix/configs/ft2004_aarch64_dsk_posix.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/phytiumpi_aarch32_firefly_posix.config b/example/system/posix/configs/phytiumpi_aarch32_firefly_posix.config index 1ca1fe1b..d97b691c 100644 --- a/example/system/posix/configs/phytiumpi_aarch32_firefly_posix.config +++ b/example/system/posix/configs/phytiumpi_aarch32_firefly_posix.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/configs/phytiumpi_aarch64_firefly_posix.config b/example/system/posix/configs/phytiumpi_aarch64_firefly_posix.config index 991065f0..66ff1d4e 100644 --- a/example/system/posix/configs/phytiumpi_aarch64_firefly_posix.config +++ b/example/system/posix/configs/phytiumpi_aarch64_firefly_posix.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/sdkconfig b/example/system/posix/sdkconfig index 991065f0..66ff1d4e 100644 --- a/example/system/posix/sdkconfig +++ b/example/system/posix/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/system/posix/sdkconfig.h b/example/system/posix/sdkconfig.h index 7e83fee2..937b2796 100644 --- a/example/system/posix/sdkconfig.h +++ b/example/system/posix/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/example/template/configs/d2000_aarch32_test_eg.config b/example/template/configs/d2000_aarch32_test_eg.config index 4c5ef7a9..87a407ff 100644 --- a/example/template/configs/d2000_aarch32_test_eg.config +++ b/example/template/configs/d2000_aarch32_test_eg.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/d2000_aarch64_test_eg.config b/example/template/configs/d2000_aarch64_test_eg.config index 05404329..3cf1014e 100644 --- a/example/template/configs/d2000_aarch64_test_eg.config +++ b/example/template/configs/d2000_aarch64_test_eg.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 # CONFIG_TARGET_FT2004 is not set CONFIG_TARGET_D2000=y # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="d2000" CONFIG_SOC_CORE_NUM=8 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/e2000d_aarch32_demo_eg.config b/example/template/configs/e2000d_aarch32_demo_eg.config index 70831ce9..fd0eab4d 100644 --- a/example/template/configs/e2000d_aarch32_demo_eg.config +++ b/example/template/configs/e2000d_aarch32_demo_eg.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -112,6 +113,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -307,6 +309,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -316,6 +319,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -338,6 +343,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/e2000d_aarch64_demo_eg.config b/example/template/configs/e2000d_aarch64_demo_eg.config index c6b3a233..8d9cd967 100644 --- a/example/template/configs/e2000d_aarch64_demo_eg.config +++ b/example/template/configs/e2000d_aarch64_demo_eg.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000D=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="d" CONFIG_SOC_CORE_NUM=2 @@ -106,6 +107,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -296,6 +298,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -305,6 +308,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -327,6 +332,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/e2000q_aarch32_demo_eg.config b/example/template/configs/e2000q_aarch32_demo_eg.config index b42aeeed..e24dfce4 100644 --- a/example/template/configs/e2000q_aarch32_demo_eg.config +++ b/example/template/configs/e2000q_aarch32_demo_eg.config @@ -53,6 +53,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -111,6 +112,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -306,6 +308,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -315,6 +318,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -337,6 +342,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/e2000q_aarch64_demo_eg.config b/example/template/configs/e2000q_aarch64_demo_eg.config index 96bcba6e..08c2e997 100644 --- a/example/template/configs/e2000q_aarch64_demo_eg.config +++ b/example/template/configs/e2000q_aarch64_demo_eg.config @@ -47,6 +47,7 @@ CONFIG_TARGET_E2000Q=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="e2000" CONFIG_TARGET_TYPE_NAME="q" CONFIG_SOC_CORE_NUM=4 @@ -105,6 +106,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -295,6 +297,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -304,6 +307,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -326,6 +331,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/ft2004_aarch32_dsk_eg.config b/example/template/configs/ft2004_aarch32_dsk_eg.config index e57bf0a3..5beaaa18 100644 --- a/example/template/configs/ft2004_aarch32_dsk_eg.config +++ b/example/template/configs/ft2004_aarch32_dsk_eg.config @@ -54,6 +54,7 @@ CONFIG_FMMU_NUM_L2_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -99,6 +100,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/ft2004_aarch64_dsk_eg.config b/example/template/configs/ft2004_aarch64_dsk_eg.config index b86d6286..1efdb7f1 100644 --- a/example/template/configs/ft2004_aarch64_dsk_eg.config +++ b/example/template/configs/ft2004_aarch64_dsk_eg.config @@ -48,6 +48,7 @@ CONFIG_MAX_XLAT_TABLES=256 CONFIG_TARGET_FT2004=y # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="ft2004" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -93,6 +94,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -283,6 +285,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -292,6 +295,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -314,6 +319,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/phytiumpi_aarch32_firefly_eg.config b/example/template/configs/phytiumpi_aarch32_firefly_eg.config index f8ccbfb9..62b34a3c 100644 --- a/example/template/configs/phytiumpi_aarch32_firefly_eg.config +++ b/example/template/configs/phytiumpi_aarch32_firefly_eg.config @@ -53,6 +53,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -110,6 +111,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -305,6 +307,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -314,6 +317,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -336,6 +341,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/configs/phytiumpi_aarch64_firefly_eg.config b/example/template/configs/phytiumpi_aarch64_firefly_eg.config index 0cc866a6..91b20200 100644 --- a/example/template/configs/phytiumpi_aarch64_firefly_eg.config +++ b/example/template/configs/phytiumpi_aarch64_firefly_eg.config @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/sdkconfig b/example/template/sdkconfig index 0cc866a6..91b20200 100644 --- a/example/template/sdkconfig +++ b/example/template/sdkconfig @@ -47,6 +47,7 @@ CONFIG_TARGET_PHYTIUMPI=y # CONFIG_TARGET_FT2004 is not set # CONFIG_TARGET_D2000 is not set # CONFIG_TARGET_PD2308 is not set +# CONFIG_TARGET_QEMU_VIRT is not set CONFIG_SOC_NAME="phytiumpi" CONFIG_SOC_CORE_NUM=4 CONFIG_F32BIT_MEMORY_ADDRESS=0x80000000 @@ -104,6 +105,7 @@ CONFIG_LOG_ERROR=y CONFIG_USE_DEFAULT_INTERRUPT_CONFIG=y CONFIG_INTERRUPT_ROLE_MASTER=y # CONFIG_INTERRUPT_ROLE_SLAVE is not set +# CONFIG_INTERRUPT_ROLE_NONE is not set # end of Sdk common configuration # @@ -294,6 +296,7 @@ CONFIG_FREERTOS_USE_UART=y # Third-party configuration # # CONFIG_USE_LWIP is not set +# CONFIG_USE_MBEDTLS is not set CONFIG_USE_LETTER_SHELL=y # @@ -303,6 +306,8 @@ CONFIG_LS_PL011_UART=y CONFIG_DEFAULT_LETTER_SHELL_USE_UART1=y # CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set # CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set +CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE=y +# CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set # end of Letter Shell Configuration # CONFIG_USE_AMP is not set @@ -325,6 +330,8 @@ CONFIG_USE_TLSF=y # CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y CONFIG_FREERTOS_HZ=1000 +CONFIG_NON_SECURE_PHYSICAL_TIMER=y +# CONFIG_NON_SECURE_VIRTUAL_TIMER is not set CONFIG_FREERTOS_MAX_PRIORITIES=32 CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES=13 CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES=11 diff --git a/example/template/sdkconfig.h b/example/template/sdkconfig.h index a23c6172..92fcfd5d 100644 --- a/example/template/sdkconfig.h +++ b/example/template/sdkconfig.h @@ -44,6 +44,7 @@ /* CONFIG_TARGET_FT2004 is not set */ /* CONFIG_TARGET_D2000 is not set */ /* CONFIG_TARGET_PD2308 is not set */ +/* CONFIG_TARGET_QEMU_VIRT is not set */ #define CONFIG_SOC_NAME "phytiumpi" #define CONFIG_SOC_CORE_NUM 4 #define CONFIG_F32BIT_MEMORY_ADDRESS 0x80000000 @@ -96,6 +97,7 @@ #define CONFIG_USE_DEFAULT_INTERRUPT_CONFIG #define CONFIG_INTERRUPT_ROLE_MASTER /* CONFIG_INTERRUPT_ROLE_SLAVE is not set */ +/* CONFIG_INTERRUPT_ROLE_NONE is not set */ /* end of Sdk common configuration */ /* Drivers configuration */ @@ -260,6 +262,7 @@ /* Third-party configuration */ /* CONFIG_USE_LWIP is not set */ +/* CONFIG_USE_MBEDTLS is not set */ #define CONFIG_USE_LETTER_SHELL /* Letter Shell Configuration */ @@ -268,6 +271,8 @@ #define CONFIG_DEFAULT_LETTER_SHELL_USE_UART1 /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART0 is not set */ /* CONFIG_DEFAULT_LETTER_SHELL_USE_UART2 is not set */ +#define CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE +/* CONFIG_LETTER_SHELL_UART_POLLED_MODE is not set */ /* end of Letter Shell Configuration */ /* CONFIG_USE_AMP is not set */ /* CONFIG_USE_YMODEM is not set */ @@ -288,6 +293,8 @@ #define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER #define CONFIG_FREERTOS_HZ 1000 +#define CONFIG_NON_SECURE_PHYSICAL_TIMER +/* CONFIG_NON_SECURE_VIRTUAL_TIMER is not set */ #define CONFIG_FREERTOS_MAX_PRIORITIES 32 #define CONFIG_FREERTOS_KERNEL_INTERRUPT_PRIORITIES 13 #define CONFIG_FREERTOS_MAX_API_CALL_INTERRUPT_PRIORITIES 11 diff --git a/install.py b/install.py index ecbbfed7..d54482f6 100755 --- a/install.py +++ b/install.py @@ -36,7 +36,7 @@ freertos_sdk_path = install_path print("Standalone SDK at {}".format(freertos_sdk_path)) # Add standalone sdk -standalone_sdk_v="c38dcff60bf78f1612429c3d80c3e1bc962dd462" +standalone_sdk_v="78f82a7628b393e58cd7b9b77112d08fc75b4f9b" if (install_platform == windows_x64): standalone_path=freertos_sdk_path + '\\standalone' else: diff --git a/third-party/freertos/freertos.kconfig b/third-party/freertos/freertos.kconfig index 3ce031c9..f983bd84 100644 --- a/third-party/freertos/freertos.kconfig +++ b/third-party/freertos/freertos.kconfig @@ -15,7 +15,22 @@ menu "FreeRTOS Kernel Configuration" default 1000 help Select the tick rate at which FreeRTOS does pre-emptive context switching. - + + choice + prompt "Freertos tick interrupt source" + default NON_SECURE_PHYSICAL_TIMER + + config NON_SECURE_PHYSICAL_TIMER + bool "Non-secure Physical Timer" + help + "Use the Physical Timer for timing operations." + + config NON_SECURE_VIRTUAL_TIMER + bool "Non-secure Virtual Timer" + help + "Use the Virtual Timer for timing operations." + endchoice + config FREERTOS_MAX_PRIORITIES int "Max task priority" range 1 32 diff --git a/third-party/freertos/portable/GCC/ft_platform/aarch64/port.c b/third-party/freertos/portable/GCC/ft_platform/aarch64/port.c index 718c3ff5..7f56dd7b 100644 --- a/third-party/freertos/portable/GCC/ft_platform/aarch64/port.c +++ b/third-party/freertos/portable/GCC/ft_platform/aarch64/port.c @@ -129,6 +129,16 @@ point is zero. */ #define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) #define portBIT_0_SET ( ( uint8_t ) 0x01 ) +/* Let the user override the pre-loading of the initial LR with the address of + * prvTaskExitError() in case it messes up unwinding of the stack in the + * debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + + /*-----------------------------------------------------------*/ /* @@ -137,6 +147,11 @@ point is zero. */ */ extern void vPortRestoreTaskContext(void); +/* + * Used to catch tasks that attempt to return from their implementing function. + */ +static void prvTaskExitError( void ); + /*-----------------------------------------------------------*/ /* A variable is used to keep track of the critical section nesting. This @@ -243,7 +258,7 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC pxTopOfStack--; *pxTopOfStack = (StackType_t)0x00; /* XZR - has no effect, used so there are an even number of registers. */ pxTopOfStack--; - *pxTopOfStack = (StackType_t)0x00; /* R30 - procedure call link register. */ + *pxTopOfStack = (StackType_t)portTASK_RETURN_ADDRESS; /* R30 - procedure call link register. */ pxTopOfStack--; *pxTopOfStack = portINITIAL_PSTATE; @@ -286,6 +301,23 @@ StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxC return pxTopOfStack; } + +static void prvTaskExitError( void ) +{ + /* A function that implements a task must not exit or attempt to return to + * its caller as there is nothing to return to. If a task wants to exit it + * should instead call vTaskDelete( NULL ). + * + * Artificially force an assert() to be triggered if configASSERT() is + * defined, then stop here so application writers can catch the error. */ + configASSERT( ullCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); + + for( ; ; ) + { + } +} + /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler(void) diff --git a/third-party/freertos/portable/freertos_configs.c b/third-party/freertos/portable/freertos_configs.c index 1504217e..6361ee2b 100644 --- a/third-party/freertos/portable/freertos_configs.c +++ b/third-party/freertos/portable/freertos_configs.c @@ -36,7 +36,15 @@ #include "fcpu_info.h" #include "fassert.h" #include "fexception.h" +#include "sdkconfig.h" +#ifdef CONFIG_NON_SECURE_PHYSICAL_TIMER + #define USING_GENERIC_TIMER_ID GENERIC_TIMER_ID0 + #define USING_GENERIC_TIMER_IRQ_ID GENERIC_TIMER_NS_IRQ_NUM +#elif defined CONFIG_NON_SECURE_VIRTUAL_TIMER + #define USING_GENERIC_TIMER_ID GENERIC_TIMER_ID1 + #define USING_GENERIC_TIMER_IRQ_ID GENERIC_VTIMER_IRQ_NUM +#endif static volatile u32 is_in_irq = 0 ; @@ -75,24 +83,24 @@ static u32 cntfrq; /* System frequency */ void vConfigureTickInterrupt(void) { /* Disable the timer */ - GenericTimerStop(GENERIC_TIMER_ID0); + GenericTimerStop(USING_GENERIC_TIMER_ID); /* Get system frequency */ cntfrq = GenericTimerFrequecy(); /* Set tick rate */ - GenericTimerSetTimerValue(GENERIC_TIMER_ID0, cntfrq / configTICK_RATE_HZ); - GenericTimerInterruptEnable(GENERIC_TIMER_ID0); + GenericTimerSetTimerValue(USING_GENERIC_TIMER_ID, cntfrq / configTICK_RATE_HZ); + GenericTimerInterruptEnable(USING_GENERIC_TIMER_ID); /* Set as the lowest priority */ - InterruptSetPriority(GENERIC_TIMER_NS_IRQ_NUM, configKERNEL_INTERRUPT_PRIORITY); - InterruptUmask(GENERIC_TIMER_NS_IRQ_NUM); + InterruptSetPriority(USING_GENERIC_TIMER_IRQ_ID, configKERNEL_INTERRUPT_PRIORITY); + InterruptUmask(USING_GENERIC_TIMER_IRQ_ID); - GenericTimerStart(GENERIC_TIMER_ID0); + GenericTimerStart(USING_GENERIC_TIMER_ID); } void vClearTickInterrupt(void) { - GenericTimerSetTimerValue(GENERIC_TIMER_ID0, cntfrq / configTICK_RATE_HZ); + GenericTimerSetTimerValue(USING_GENERIC_TIMER_ID, cntfrq / configTICK_RATE_HZ); } volatile unsigned int gCpuRuntime; @@ -107,7 +115,7 @@ void vApplicationInterruptHandler(uint32_t ulICCIAR) ulInterruptID = ulICCIAR & 0x3FFUL; /* call handler function */ - if (ulInterruptID == GENERIC_TIMER_NS_IRQ_NUM) + if (ulInterruptID == USING_GENERIC_TIMER_IRQ_ID) { /* Generic Timer */ gCpuRuntime++; diff --git a/third-party/include.mk b/third-party/include.mk index 810c17e9..2c2f264d 100644 --- a/third-party/include.mk +++ b/third-party/include.mk @@ -51,3 +51,7 @@ endif ifdef CONFIG_USE_CHERRY_USB include $(SDK_DIR)/third-party/cherryusb/include.mk endif + +ifdef CONFIG_USE_MBEDTLS +include $(FREERTOS_SDK_DIR)/third-party/mbedtls-3.6/include.mk +endif diff --git a/third-party/letter-shell-3.1/Kconfig b/third-party/letter-shell-3.1/Kconfig index 2f9a2c7e..6247101f 100644 --- a/third-party/letter-shell-3.1/Kconfig +++ b/third-party/letter-shell-3.1/Kconfig @@ -27,4 +27,19 @@ menu "Letter Shell Configuration" endif endchoice # LETTER_SHELL_USART_TYPE + + choice + prompt "Uart Mode" + default LETTER_SHELL_UART_INTERRUPT_MODE + + config LETTER_SHELL_UART_INTERRUPT_MODE + bool "Interrupt Mode" + help + "Use the interrupt mode for letter shell." + + config LETTER_SHELL_UART_POLLED_MODE + bool "Polled Mode" + help + "Use the polled mode for letter shell ." + endchoice endmenu \ No newline at end of file diff --git a/third-party/letter-shell-3.1/port/pl011/fpl011_os_port.c b/third-party/letter-shell-3.1/port/pl011/fpl011_os_port.c index 2e6c7e5e..fbfcc535 100644 --- a/third-party/letter-shell-3.1/port/pl011/fpl011_os_port.c +++ b/third-party/letter-shell-3.1/port/pl011/fpl011_os_port.c @@ -49,7 +49,7 @@ static char data[64]; #endif extern void FtFreertosUartIntrInit(FtFreertosUart *uart_p); - +#ifdef CONFIG_LETTER_SHELL_UART_INTERRUPT_MODE /** * @brief 用户shell写 * @@ -57,7 +57,6 @@ extern void FtFreertosUartIntrInit(FtFreertosUart *uart_p); */ void LSUserShellWrite(char data) { - // FtFreertosUartBlcokingSend(&os_uart1, &data, 1); FPl011Send(&os_uart1.bsp_uart, &data, 1); } @@ -101,3 +100,57 @@ void LSSerialWaitLoop(void) } vTaskDelete(NULL); } + +#elif defined CONFIG_LETTER_SHELL_UART_POLLED_MODE + +#define LS_UART_WAIT_LOOP_DELAY 5 + /** + * @brief 用户shell写 + * + * @param data 数据 + */ +void LSUserShellWrite(char data) +{ + FPl011BlockSend(&os_uart1.bsp_uart, (u8 *)&data, 1); +} + +/** + * @brief 用户shell读 + * + * @param data 数据 + * @return char 状态 + */ +signed char LSUserShellRead(char *data) +{ + u32 length = 0; + length = FPl011Receive(&os_uart1.bsp_uart,(u8 *)data,1); + return (length > 0)? 1:0; +} + +void LSSerialConfig(void) +{ + s32 ret = FT_SUCCESS; + const FPl011Config * config_p; + FPl011Config config_value; + memset(&os_uart1.bsp_uart, 0, sizeof(os_uart1.bsp_uart)); + config_p = FPl011LookupConfig(LETTER_SHELL_UART_ID) ; + memcpy(&config_value, config_p, sizeof(FPl011Config)); + /* 初始化PL011 */ + ret = FPl011CfgInitialize(&os_uart1.bsp_uart, &config_value); + FASSERT(FT_SUCCESS == ret); + FPl011SetOptions(&os_uart1.bsp_uart, FPL011_OPTION_UARTEN | FPL011_OPTION_RXEN | FPL011_OPTION_TXEN | FPL011_OPTION_FIFOEN ); +} + +void LSSerialWaitLoop(void) +{ + char buf; + while (TRUE) + { + buf = FPl011BlockReceive(&os_uart1.bsp_uart); + shellHandler(&shell_object, buf); + vTaskDelay(LS_UART_WAIT_LOOP_DELAY); + } +} +#endif + + diff --git a/third-party/lvgl-8.3/port/lv_port_disp.c b/third-party/lvgl-8.3/port/lv_port_disp.c index f4b77c5d..d654bcc7 100644 --- a/third-party/lvgl-8.3/port/lv_port_disp.c +++ b/third-party/lvgl-8.3/port/lv_port_disp.c @@ -58,12 +58,12 @@ void FMediaDispFramebuffer(FDcDp *instance) if ((rtt_fbp[0] == NULL)) { - rtt_fbp[0] = (lv_color_int_t *)instance->user_config[0].fb_virtual; - multi_mode = instance->user_config[0].multi_mode; + rtt_fbp[0] = (lv_color_int_t *)instance->dc_instance_p[0].fb_virtual; + multi_mode = instance->dc_instance_p[0].fb_virtual; } else { - rtt_fbp[1] = (lv_color_int_t *)instance->user_config[1].fb_virtual; + rtt_fbp[1] = (lv_color_int_t *) instance->dc_instance_p[1].fb_virtual; } return; diff --git a/third-party/mbedtls-3.6/Kconfig b/third-party/mbedtls-3.6/Kconfig new file mode 100644 index 00000000..b832fe10 --- /dev/null +++ b/third-party/mbedtls-3.6/Kconfig @@ -0,0 +1,3 @@ +menu "MBEDTLS Freertos Port Configuration" + +endmenu \ No newline at end of file diff --git a/third-party/mbedtls-3.6/include.mk b/third-party/mbedtls-3.6/include.mk new file mode 100644 index 00000000..611e3493 --- /dev/null +++ b/third-party/mbedtls-3.6/include.mk @@ -0,0 +1,14 @@ +ifdef CONFIG_USE_MBEDTLS + +THIRDP_CUR_DIR := $(FREERTOS_SDK_DIR)/third-party + +# src files +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6 +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6/include +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6/include/mbedtls +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6/library +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6/ports +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6/ports/inc +BUILD_INC_PATH_DIR += $(THIRDP_CUR_DIR)/mbedtls-3.6/ports/src + +endif #CONFIG_USE_MBEDTLS \ No newline at end of file diff --git a/third-party/mbedtls-3.6/include/.gitignore b/third-party/mbedtls-3.6/include/.gitignore new file mode 100644 index 00000000..bf67d02e --- /dev/null +++ b/third-party/mbedtls-3.6/include/.gitignore @@ -0,0 +1,4 @@ +Makefile +*.sln +*.vcxproj +mbedtls/check_config diff --git a/third-party/mbedtls-3.6/include/CMakeLists.txt b/third-party/mbedtls-3.6/include/CMakeLists.txt new file mode 100644 index 00000000..c2f2bd4e --- /dev/null +++ b/third-party/mbedtls-3.6/include/CMakeLists.txt @@ -0,0 +1,16 @@ +option(INSTALL_MBEDTLS_HEADERS "Install mbed TLS headers." ON) + +if(INSTALL_MBEDTLS_HEADERS) + + file(GLOB headers "mbedtls/*.h") + + install(FILES ${headers} + DESTINATION include/mbedtls + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + +endif(INSTALL_MBEDTLS_HEADERS) + +# Make config.h available in an out-of-source build. ssl-opt.sh requires it. +if (ENABLE_TESTING AND NOT ${CMAKE_CURRENT_BINARY_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) + link_to_source(mbedtls) +endif() diff --git a/third-party/mbedtls-3.6/include/mbedtls/aes.h b/third-party/mbedtls-3.6/include/mbedtls/aes.h new file mode 100644 index 00000000..a187796b --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/aes.h @@ -0,0 +1,443 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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: +

*/ +} +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 */ +#include "aes_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/aesni.h b/third-party/mbedtls-3.6/include/mbedtls/aesni.h new file mode 100644 index 00000000..845da74e --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/aesni.h @@ -0,0 +1,143 @@ +/** + * \file aesni.h + * + * \brief AES-NI for hardware AES acceleration on some Intel processors + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_AESNI_H +#define MBEDTLS_AESNI_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "aes.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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/arc4.h b/third-party/mbedtls-3.6/include/mbedtls/arc4.h new file mode 100644 index 00000000..50b6f483 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/arc4.h @@ -0,0 +1,174 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "arc4_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/asn1.h b/third-party/mbedtls-3.6/include/mbedtls/asn1.h new file mode 100644 index 00000000..0e596bca --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/asn1.h @@ -0,0 +1,383 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "bignum.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/asn1write.h b/third-party/mbedtls-3.6/include/mbedtls/asn1write.h new file mode 100644 index 00000000..93c570a4 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/asn1write.h @@ -0,0 +1,274 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.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 This function works backwards in data buffer. + * + * \param p The reference to the current position pointer. + * \param start The start of the buffer, for bounds-checking. + * \param buf The bitstring to write. + * \param bits The total number of bits in the bitstring. + * + * \return The number of bytes written to \p p on success. + * \return A negative error code on failure. + */ +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 This 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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/base64.h b/third-party/mbedtls-3.6/include/mbedtls/base64.h new file mode 100644 index 00000000..f30be4ac --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/base64.h @@ -0,0 +1,120 @@ +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/bignum.h b/third-party/mbedtls-3.6/include/mbedtls/bignum.h new file mode 100644 index 00000000..a2fa3bda --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/bignum.h @@ -0,0 +1,809 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 window 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; /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + 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 Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/blowfish.h b/third-party/mbedtls-3.6/include/mbedtls/blowfish.h new file mode 100644 index 00000000..60017af3 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/blowfish.h @@ -0,0 +1,230 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +#endif /* blowfish.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/bn_mul.h b/third-party/mbedtls-3.6/include/mbedtls/bn_mul.h new file mode 100644 index 00000000..d0b10223 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/bn_mul.h @@ -0,0 +1,924 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.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 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#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", "ebx", "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", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#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", "lo", "hi" \ + ); + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/camellia.h b/third-party/mbedtls-3.6/include/mbedtls/camellia.h new file mode 100644 index 00000000..1ed0ca4b --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/camellia.h @@ -0,0 +1,262 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "camellia_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ccm.h b/third-party/mbedtls-3.6/include/mbedtls/ccm.h new file mode 100644 index 00000000..80cc1f68 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ccm.h @@ -0,0 +1,207 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.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 */ +#include "ccm_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/certs.h b/third-party/mbedtls-3.6/include/mbedtls/certs.h new file mode 100644 index 00000000..86722884 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/certs.h @@ -0,0 +1,131 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all CA certificates in PEM format if available */ +extern const char mbedtls_test_cas_pem[]; +extern const size_t mbedtls_test_cas_pem_len; +#endif + +/* List of all CA certificates, terminated by NULL */ +extern const char * mbedtls_test_cas[]; +extern const size_t mbedtls_test_cas_len[]; + +/* + * Convenience for users who just want a certificate: + * RSA by default, or ECDSA if RSA is not available + */ +extern const char * mbedtls_test_ca_crt; +extern const size_t mbedtls_test_ca_crt_len; +extern const char * mbedtls_test_ca_key; +extern const size_t mbedtls_test_ca_key_len; +extern const char * mbedtls_test_ca_pwd; +extern const size_t mbedtls_test_ca_pwd_len; +extern const char * mbedtls_test_srv_crt; +extern const size_t mbedtls_test_srv_crt_len; +extern const char * mbedtls_test_srv_key; +extern const size_t mbedtls_test_srv_key_len; +extern const char * mbedtls_test_cli_crt; +extern const size_t mbedtls_test_cli_crt_len; +extern const char * mbedtls_test_cli_key; +extern const size_t mbedtls_test_cli_key_len; + +#if defined(MBEDTLS_ECDSA_C) +extern const char mbedtls_test_ca_crt_ec[]; +extern const size_t mbedtls_test_ca_crt_ec_len; +extern const char mbedtls_test_ca_key_ec[]; +extern const size_t mbedtls_test_ca_key_ec_len; +extern const char mbedtls_test_ca_pwd_ec[]; +extern const size_t mbedtls_test_ca_pwd_ec_len; +extern const char mbedtls_test_srv_crt_ec[]; +extern const size_t mbedtls_test_srv_crt_ec_len; +extern const char mbedtls_test_srv_key_ec[]; +extern const size_t mbedtls_test_srv_key_ec_len; +extern const char mbedtls_test_cli_crt_ec[]; +extern const size_t mbedtls_test_cli_crt_ec_len; +extern const char mbedtls_test_cli_key_ec[]; +extern const size_t mbedtls_test_cli_key_ec_len; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const char mbedtls_test_ca_crt_rsa[]; +extern const size_t mbedtls_test_ca_crt_rsa_len; +extern const char mbedtls_test_ca_key_rsa[]; +extern const size_t mbedtls_test_ca_key_rsa_len; +extern const char mbedtls_test_ca_pwd_rsa[]; +extern const size_t mbedtls_test_ca_pwd_rsa_len; +extern const char mbedtls_test_srv_crt_rsa[]; +extern const size_t mbedtls_test_srv_crt_rsa_len; +extern const char mbedtls_test_srv_key_rsa[]; +extern const size_t mbedtls_test_srv_key_rsa_len; +extern const char mbedtls_test_cli_crt_rsa[]; +extern const size_t mbedtls_test_cli_crt_rsa_len; +extern const char mbedtls_test_cli_key_rsa[]; +extern const size_t mbedtls_test_cli_key_rsa_len; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/check_config.h b/third-party/mbedtls-3.6/include/mbedtls/check_config.h new file mode 100644 index 00000000..654c6ba5 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/check_config.h @@ -0,0 +1,753 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && !( \ + defined(MBEDTLS_ECP_ALT) || \ + defined(MBEDTLS_CTR_DRBG_C) || \ + defined(MBEDTLS_HMAC_DRBG_C) || \ + defined(MBEDTLS_SHA512_C) || \ + defined(MBEDTLS_SHA256_C) || \ + defined(MBEDTLS_ECP_NO_INTERNAL_RNG)) +#error "MBEDTLS_ECP_C requires a DRBG or SHA-2 module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#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(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + +#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_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#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_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \ + !(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_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#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_CERTS_C) && !defined(MBEDTLS_X509_USE_C) +#error "MBEDTLS_CERTS_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 empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/cipher.h b/third-party/mbedtls-3.6/include/mbedtls/cipher.h new file mode 100644 index 00000000..7f40b7ec --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/cipher.h @@ -0,0 +1,777 @@ +/** + * \file cipher.h + * + * \brief The generic cipher wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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) || defined(MBEDTLS_CIPHER_NULL_CIPHER) +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/cipher_internal.h b/third-party/mbedtls-3.6/include/mbedtls/cipher_internal.h new file mode 100644 index 00000000..758cf95a --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/cipher_internal.h @@ -0,0 +1,135 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/cmac.h b/third-party/mbedtls-3.6/include/mbedtls/cmac.h new file mode 100644 index 00000000..dbfc1bbf --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/cmac.h @@ -0,0 +1,239 @@ +/** + * \file cmac.h + * + * \brief The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /* The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /* The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t unprocessed_len; +}; + +/** + * \brief This function sets the CMAC key, and prepares to authenticate + * the input data. + * Must be called with an initialized cipher context. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types:
    + *
  • MBEDTLS_CIPHER_AES_128_ECB
  • + *
  • MBEDTLS_CIPHER_AES_192_ECB
  • + *
  • MBEDTLS_CIPHER_AES_256_ECB
  • + *
  • MBEDTLS_CIPHER_DES_EDE3_ECB
+ * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success, or a cipher-specific error code. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * It is called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish(). + * Can be called repeatedly. + * + * \param ctx The cipher context used for the CMAC operation. + * \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_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the CMAC operation, and writes + * the result to the output buffer. + * + * It is called after mbedtls_cipher_cmac_update(). + * It can be followed by mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_update(), or mbedtls_cipher_free(). + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function prepares the authentication of another + * message with the same key as the previous CMAC + * operation. + * + * It is called after mbedtls_cipher_cmac_finish() + * and before mbedtls_cipher_cmac_update(). + * + * \param ctx The cipher context used for the CMAC operation. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \returns \c 0 on success, or #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +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 ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * 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). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#ifdef __cplusplus +} +#endif + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \return \c 0 on success, or \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/compat-1.3.h b/third-party/mbedtls-3.6/include/mbedtls/compat-1.3.h new file mode 100644 index 00000000..b0103cc8 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/compat-1.3.h @@ -0,0 +1,2555 @@ +/** + * \file compat-1.3.h + * + * \brief Compatibility definitions for using mbed TLS with client code written + * for the PolarSSL naming conventions. + * + * \deprecated Use the new names directly instead + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) + +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Including compat-1.3.h is deprecated" +#endif + +#ifndef MBEDTLS_COMPAT13_H +#define MBEDTLS_COMPAT13_H + +/* + * config.h options + */ +#if defined MBEDTLS_AESNI_C +#define POLARSSL_AESNI_C MBEDTLS_AESNI_C +#endif +#if defined MBEDTLS_AES_ALT +#define POLARSSL_AES_ALT MBEDTLS_AES_ALT +#endif +#if defined MBEDTLS_AES_C +#define POLARSSL_AES_C MBEDTLS_AES_C +#endif +#if defined MBEDTLS_AES_ROM_TABLES +#define POLARSSL_AES_ROM_TABLES MBEDTLS_AES_ROM_TABLES +#endif +#if defined MBEDTLS_ARC4_ALT +#define POLARSSL_ARC4_ALT MBEDTLS_ARC4_ALT +#endif +#if defined MBEDTLS_ARC4_C +#define POLARSSL_ARC4_C MBEDTLS_ARC4_C +#endif +#if defined MBEDTLS_ASN1_PARSE_C +#define POLARSSL_ASN1_PARSE_C MBEDTLS_ASN1_PARSE_C +#endif +#if defined MBEDTLS_ASN1_WRITE_C +#define POLARSSL_ASN1_WRITE_C MBEDTLS_ASN1_WRITE_C +#endif +#if defined MBEDTLS_BASE64_C +#define POLARSSL_BASE64_C MBEDTLS_BASE64_C +#endif +#if defined MBEDTLS_BIGNUM_C +#define POLARSSL_BIGNUM_C MBEDTLS_BIGNUM_C +#endif +#if defined MBEDTLS_BLOWFISH_ALT +#define POLARSSL_BLOWFISH_ALT MBEDTLS_BLOWFISH_ALT +#endif +#if defined MBEDTLS_BLOWFISH_C +#define POLARSSL_BLOWFISH_C MBEDTLS_BLOWFISH_C +#endif +#if defined MBEDTLS_CAMELLIA_ALT +#define POLARSSL_CAMELLIA_ALT MBEDTLS_CAMELLIA_ALT +#endif +#if defined MBEDTLS_CAMELLIA_C +#define POLARSSL_CAMELLIA_C MBEDTLS_CAMELLIA_C +#endif +#if defined MBEDTLS_CAMELLIA_SMALL_MEMORY +#define POLARSSL_CAMELLIA_SMALL_MEMORY MBEDTLS_CAMELLIA_SMALL_MEMORY +#endif +#if defined MBEDTLS_CCM_C +#define POLARSSL_CCM_C MBEDTLS_CCM_C +#endif +#if defined MBEDTLS_CERTS_C +#define POLARSSL_CERTS_C MBEDTLS_CERTS_C +#endif +#if defined MBEDTLS_CIPHER_C +#define POLARSSL_CIPHER_C MBEDTLS_CIPHER_C +#endif +#if defined MBEDTLS_CIPHER_MODE_CBC +#define POLARSSL_CIPHER_MODE_CBC MBEDTLS_CIPHER_MODE_CBC +#endif +#if defined MBEDTLS_CIPHER_MODE_CFB +#define POLARSSL_CIPHER_MODE_CFB MBEDTLS_CIPHER_MODE_CFB +#endif +#if defined MBEDTLS_CIPHER_MODE_CTR +#define POLARSSL_CIPHER_MODE_CTR MBEDTLS_CIPHER_MODE_CTR +#endif +#if defined MBEDTLS_CIPHER_NULL_CIPHER +#define POLARSSL_CIPHER_NULL_CIPHER MBEDTLS_CIPHER_NULL_CIPHER +#endif +#if defined MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_PKCS7 +#define POLARSSL_CIPHER_PADDING_PKCS7 MBEDTLS_CIPHER_PADDING_PKCS7 +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS +#define POLARSSL_CIPHER_PADDING_ZEROS MBEDTLS_CIPHER_PADDING_ZEROS +#endif +#if defined MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#endif +#if defined MBEDTLS_CTR_DRBG_C +#define POLARSSL_CTR_DRBG_C MBEDTLS_CTR_DRBG_C +#endif +#if defined MBEDTLS_DEBUG_C +#define POLARSSL_DEBUG_C MBEDTLS_DEBUG_C +#endif +#if defined MBEDTLS_DEPRECATED_REMOVED +#define POLARSSL_DEPRECATED_REMOVED MBEDTLS_DEPRECATED_REMOVED +#endif +#if defined MBEDTLS_DEPRECATED_WARNING +#define POLARSSL_DEPRECATED_WARNING MBEDTLS_DEPRECATED_WARNING +#endif +#if defined MBEDTLS_DES_ALT +#define POLARSSL_DES_ALT MBEDTLS_DES_ALT +#endif +#if defined MBEDTLS_DES_C +#define POLARSSL_DES_C MBEDTLS_DES_C +#endif +#if defined MBEDTLS_DHM_C +#define POLARSSL_DHM_C MBEDTLS_DHM_C +#endif +#if defined MBEDTLS_ECDH_C +#define POLARSSL_ECDH_C MBEDTLS_ECDH_C +#endif +#if defined MBEDTLS_ECDSA_C +#define POLARSSL_ECDSA_C MBEDTLS_ECDSA_C +#endif +#if defined MBEDTLS_ECDSA_DETERMINISTIC +#define POLARSSL_ECDSA_DETERMINISTIC MBEDTLS_ECDSA_DETERMINISTIC +#endif +#if defined MBEDTLS_ECP_C +#define POLARSSL_ECP_C MBEDTLS_ECP_C +#endif +#if defined MBEDTLS_ECP_DP_BP256R1_ENABLED +#define POLARSSL_ECP_DP_BP256R1_ENABLED MBEDTLS_ECP_DP_BP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP384R1_ENABLED +#define POLARSSL_ECP_DP_BP384R1_ENABLED MBEDTLS_ECP_DP_BP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_BP512R1_ENABLED +#define POLARSSL_ECP_DP_BP512R1_ENABLED MBEDTLS_ECP_DP_BP512R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define POLARSSL_ECP_DP_M255_ENABLED MBEDTLS_ECP_DP_CURVE25519_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define POLARSSL_ECP_DP_SECP192K1_ENABLED MBEDTLS_ECP_DP_SECP192K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define POLARSSL_ECP_DP_SECP192R1_ENABLED MBEDTLS_ECP_DP_SECP192R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define POLARSSL_ECP_DP_SECP224K1_ENABLED MBEDTLS_ECP_DP_SECP224K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define POLARSSL_ECP_DP_SECP224R1_ENABLED MBEDTLS_ECP_DP_SECP224R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define POLARSSL_ECP_DP_SECP256K1_ENABLED MBEDTLS_ECP_DP_SECP256K1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define POLARSSL_ECP_DP_SECP256R1_ENABLED MBEDTLS_ECP_DP_SECP256R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define POLARSSL_ECP_DP_SECP384R1_ENABLED MBEDTLS_ECP_DP_SECP384R1_ENABLED +#endif +#if defined MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define POLARSSL_ECP_DP_SECP521R1_ENABLED MBEDTLS_ECP_DP_SECP521R1_ENABLED +#endif +#if defined MBEDTLS_ECP_FIXED_POINT_OPTIM +#define POLARSSL_ECP_FIXED_POINT_OPTIM MBEDTLS_ECP_FIXED_POINT_OPTIM +#endif +#if defined MBEDTLS_ECP_MAX_BITS +#define POLARSSL_ECP_MAX_BITS MBEDTLS_ECP_MAX_BITS +#endif +#if defined MBEDTLS_ECP_NIST_OPTIM +#define POLARSSL_ECP_NIST_OPTIM MBEDTLS_ECP_NIST_OPTIM +#endif +#if defined MBEDTLS_ECP_WINDOW_SIZE +#define POLARSSL_ECP_WINDOW_SIZE MBEDTLS_ECP_WINDOW_SIZE +#endif +#if defined MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#define POLARSSL_ENABLE_WEAK_CIPHERSUITES MBEDTLS_ENABLE_WEAK_CIPHERSUITES +#endif +#if defined MBEDTLS_ENTROPY_C +#define POLARSSL_ENTROPY_C MBEDTLS_ENTROPY_C +#endif +#if defined MBEDTLS_ENTROPY_FORCE_SHA256 +#define POLARSSL_ENTROPY_FORCE_SHA256 MBEDTLS_ENTROPY_FORCE_SHA256 +#endif +#if defined MBEDTLS_ERROR_C +#define POLARSSL_ERROR_C MBEDTLS_ERROR_C +#endif +#if defined MBEDTLS_ERROR_STRERROR_DUMMY +#define POLARSSL_ERROR_STRERROR_DUMMY MBEDTLS_ERROR_STRERROR_DUMMY +#endif +#if defined MBEDTLS_FS_IO +#define POLARSSL_FS_IO MBEDTLS_FS_IO +#endif +#if defined MBEDTLS_GCM_C +#define POLARSSL_GCM_C MBEDTLS_GCM_C +#endif +#if defined MBEDTLS_GENPRIME +#define POLARSSL_GENPRIME MBEDTLS_GENPRIME +#endif +#if defined MBEDTLS_HAVEGE_C +#define POLARSSL_HAVEGE_C MBEDTLS_HAVEGE_C +#endif +#if defined MBEDTLS_HAVE_ASM +#define POLARSSL_HAVE_ASM MBEDTLS_HAVE_ASM +#endif +#if defined MBEDTLS_HAVE_SSE2 +#define POLARSSL_HAVE_SSE2 MBEDTLS_HAVE_SSE2 +#endif +#if defined MBEDTLS_HAVE_TIME +#define POLARSSL_HAVE_TIME MBEDTLS_HAVE_TIME +#endif +#if defined MBEDTLS_HMAC_DRBG_C +#define POLARSSL_HMAC_DRBG_C MBEDTLS_HMAC_DRBG_C +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_INPUT +#define POLARSSL_HMAC_DRBG_MAX_INPUT MBEDTLS_HMAC_DRBG_MAX_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_REQUEST +#define POLARSSL_HMAC_DRBG_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST +#endif +#if defined MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT +#endif +#if defined MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL MBEDTLS_HMAC_DRBG_RESEED_INTERVAL +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_PSK_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +#endif +#if defined MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED +#endif +#if defined MBEDTLS_MD2_ALT +#define POLARSSL_MD2_ALT MBEDTLS_MD2_ALT +#endif +#if defined MBEDTLS_MD2_C +#define POLARSSL_MD2_C MBEDTLS_MD2_C +#endif +#if defined MBEDTLS_MD2_PROCESS_ALT +#define POLARSSL_MD2_PROCESS_ALT MBEDTLS_MD2_PROCESS_ALT +#endif +#if defined MBEDTLS_MD4_ALT +#define POLARSSL_MD4_ALT MBEDTLS_MD4_ALT +#endif +#if defined MBEDTLS_MD4_C +#define POLARSSL_MD4_C MBEDTLS_MD4_C +#endif +#if defined MBEDTLS_MD4_PROCESS_ALT +#define POLARSSL_MD4_PROCESS_ALT MBEDTLS_MD4_PROCESS_ALT +#endif +#if defined MBEDTLS_MD5_ALT +#define POLARSSL_MD5_ALT MBEDTLS_MD5_ALT +#endif +#if defined MBEDTLS_MD5_C +#define POLARSSL_MD5_C MBEDTLS_MD5_C +#endif +#if defined MBEDTLS_MD5_PROCESS_ALT +#define POLARSSL_MD5_PROCESS_ALT MBEDTLS_MD5_PROCESS_ALT +#endif +#if defined MBEDTLS_MD_C +#define POLARSSL_MD_C MBEDTLS_MD_C +#endif +#if defined MBEDTLS_MEMORY_ALIGN_MULTIPLE +#define POLARSSL_MEMORY_ALIGN_MULTIPLE MBEDTLS_MEMORY_ALIGN_MULTIPLE +#endif +#if defined MBEDTLS_MEMORY_BACKTRACE +#define POLARSSL_MEMORY_BACKTRACE MBEDTLS_MEMORY_BACKTRACE +#endif +#if defined MBEDTLS_MEMORY_BUFFER_ALLOC_C +#define POLARSSL_MEMORY_BUFFER_ALLOC_C MBEDTLS_MEMORY_BUFFER_ALLOC_C +#endif +#if defined MBEDTLS_MEMORY_DEBUG +#define POLARSSL_MEMORY_DEBUG MBEDTLS_MEMORY_DEBUG +#endif +#if defined MBEDTLS_MPI_MAX_SIZE +#define POLARSSL_MPI_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif +#if defined MBEDTLS_MPI_WINDOW_SIZE +#define POLARSSL_MPI_WINDOW_SIZE MBEDTLS_MPI_WINDOW_SIZE +#endif +#if defined MBEDTLS_NET_C +#define POLARSSL_NET_C MBEDTLS_NET_C +#endif +#if defined MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES +#endif +#if defined MBEDTLS_NO_PLATFORM_ENTROPY +#define POLARSSL_NO_PLATFORM_ENTROPY MBEDTLS_NO_PLATFORM_ENTROPY +#endif +#if defined MBEDTLS_OID_C +#define POLARSSL_OID_C MBEDTLS_OID_C +#endif +#if defined MBEDTLS_PADLOCK_C +#define POLARSSL_PADLOCK_C MBEDTLS_PADLOCK_C +#endif +#if defined MBEDTLS_PEM_PARSE_C +#define POLARSSL_PEM_PARSE_C MBEDTLS_PEM_PARSE_C +#endif +#if defined MBEDTLS_PEM_WRITE_C +#define POLARSSL_PEM_WRITE_C MBEDTLS_PEM_WRITE_C +#endif +#if defined MBEDTLS_PKCS11_C +#define POLARSSL_PKCS11_C MBEDTLS_PKCS11_C +#endif +#if defined MBEDTLS_PKCS12_C +#define POLARSSL_PKCS12_C MBEDTLS_PKCS12_C +#endif +#if defined MBEDTLS_PKCS1_V15 +#define POLARSSL_PKCS1_V15 MBEDTLS_PKCS1_V15 +#endif +#if defined MBEDTLS_PKCS1_V21 +#define POLARSSL_PKCS1_V21 MBEDTLS_PKCS1_V21 +#endif +#if defined MBEDTLS_PKCS5_C +#define POLARSSL_PKCS5_C MBEDTLS_PKCS5_C +#endif +#if defined MBEDTLS_PK_C +#define POLARSSL_PK_C MBEDTLS_PK_C +#endif +#if defined MBEDTLS_PK_PARSE_C +#define POLARSSL_PK_PARSE_C MBEDTLS_PK_PARSE_C +#endif +#if defined MBEDTLS_PK_PARSE_EC_EXTENDED +#define POLARSSL_PK_PARSE_EC_EXTENDED MBEDTLS_PK_PARSE_EC_EXTENDED +#endif +#if defined MBEDTLS_PK_RSA_ALT_SUPPORT +#define POLARSSL_PK_RSA_ALT_SUPPORT MBEDTLS_PK_RSA_ALT_SUPPORT +#endif +#if defined MBEDTLS_PK_WRITE_C +#define POLARSSL_PK_WRITE_C MBEDTLS_PK_WRITE_C +#endif +#if defined MBEDTLS_PLATFORM_C +#define POLARSSL_PLATFORM_C MBEDTLS_PLATFORM_C +#endif +#if defined MBEDTLS_PLATFORM_EXIT_ALT +#define POLARSSL_PLATFORM_EXIT_ALT MBEDTLS_PLATFORM_EXIT_ALT +#endif +#if defined MBEDTLS_PLATFORM_EXIT_MACRO +#define POLARSSL_PLATFORM_EXIT_MACRO MBEDTLS_PLATFORM_EXIT_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_ALT +#define POLARSSL_PLATFORM_FPRINTF_ALT MBEDTLS_PLATFORM_FPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_FPRINTF_MACRO +#define POLARSSL_PLATFORM_FPRINTF_MACRO MBEDTLS_PLATFORM_FPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_FREE_MACRO +#define POLARSSL_PLATFORM_FREE_MACRO MBEDTLS_PLATFORM_FREE_MACRO +#endif +#if defined MBEDTLS_PLATFORM_MEMORY +#define POLARSSL_PLATFORM_MEMORY MBEDTLS_PLATFORM_MEMORY +#endif +#if defined MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS MBEDTLS_PLATFORM_NO_STD_FUNCTIONS +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_ALT +#define POLARSSL_PLATFORM_PRINTF_ALT MBEDTLS_PLATFORM_PRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_PRINTF_MACRO +#define POLARSSL_PLATFORM_PRINTF_MACRO MBEDTLS_PLATFORM_PRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_ALT +#define POLARSSL_PLATFORM_SNPRINTF_ALT MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#if defined MBEDTLS_PLATFORM_SNPRINTF_MACRO +#define POLARSSL_PLATFORM_SNPRINTF_MACRO MBEDTLS_PLATFORM_SNPRINTF_MACRO +#endif +#if defined MBEDTLS_PLATFORM_STD_EXIT +#define POLARSSL_PLATFORM_STD_EXIT MBEDTLS_PLATFORM_STD_EXIT +#endif +#if defined MBEDTLS_PLATFORM_STD_FPRINTF +#define POLARSSL_PLATFORM_STD_FPRINTF MBEDTLS_PLATFORM_STD_FPRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_FREE +#define POLARSSL_PLATFORM_STD_FREE MBEDTLS_PLATFORM_STD_FREE +#endif +#if defined MBEDTLS_PLATFORM_STD_MEM_HDR +#define POLARSSL_PLATFORM_STD_MEM_HDR MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#if defined MBEDTLS_PLATFORM_STD_PRINTF +#define POLARSSL_PLATFORM_STD_PRINTF MBEDTLS_PLATFORM_STD_PRINTF +#endif +#if defined MBEDTLS_PLATFORM_STD_SNPRINTF +#define POLARSSL_PLATFORM_STD_SNPRINTF MBEDTLS_PLATFORM_STD_SNPRINTF +#endif +#if defined MBEDTLS_PSK_MAX_LEN +#define POLARSSL_PSK_MAX_LEN MBEDTLS_PSK_MAX_LEN +#endif +#if defined MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#define POLARSSL_REMOVE_ARC4_CIPHERSUITES MBEDTLS_REMOVE_ARC4_CIPHERSUITES +#endif +#if defined MBEDTLS_RIPEMD160_ALT +#define POLARSSL_RIPEMD160_ALT MBEDTLS_RIPEMD160_ALT +#endif +#if defined MBEDTLS_RIPEMD160_C +#define POLARSSL_RIPEMD160_C MBEDTLS_RIPEMD160_C +#endif +#if defined MBEDTLS_RIPEMD160_PROCESS_ALT +#define POLARSSL_RIPEMD160_PROCESS_ALT MBEDTLS_RIPEMD160_PROCESS_ALT +#endif +#if defined MBEDTLS_RSA_C +#define POLARSSL_RSA_C MBEDTLS_RSA_C +#endif +#if defined MBEDTLS_RSA_NO_CRT +#define POLARSSL_RSA_NO_CRT MBEDTLS_RSA_NO_CRT +#endif +#if defined MBEDTLS_SELF_TEST +#define POLARSSL_SELF_TEST MBEDTLS_SELF_TEST +#endif +#if defined MBEDTLS_SHA1_ALT +#define POLARSSL_SHA1_ALT MBEDTLS_SHA1_ALT +#endif +#if defined MBEDTLS_SHA1_C +#define POLARSSL_SHA1_C MBEDTLS_SHA1_C +#endif +#if defined MBEDTLS_SHA1_PROCESS_ALT +#define POLARSSL_SHA1_PROCESS_ALT MBEDTLS_SHA1_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA256_ALT +#define POLARSSL_SHA256_ALT MBEDTLS_SHA256_ALT +#endif +#if defined MBEDTLS_SHA256_C +#define POLARSSL_SHA256_C MBEDTLS_SHA256_C +#endif +#if defined MBEDTLS_SHA256_PROCESS_ALT +#define POLARSSL_SHA256_PROCESS_ALT MBEDTLS_SHA256_PROCESS_ALT +#endif +#if defined MBEDTLS_SHA512_ALT +#define POLARSSL_SHA512_ALT MBEDTLS_SHA512_ALT +#endif +#if defined MBEDTLS_SHA512_C +#define POLARSSL_SHA512_C MBEDTLS_SHA512_C +#endif +#if defined MBEDTLS_SHA512_PROCESS_ALT +#define POLARSSL_SHA512_PROCESS_ALT MBEDTLS_SHA512_PROCESS_ALT +#endif +#if defined MBEDTLS_SSL_ALL_ALERT_MESSAGES +#define POLARSSL_SSL_ALL_ALERT_MESSAGES MBEDTLS_SSL_ALL_ALERT_MESSAGES +#endif +#if defined MBEDTLS_SSL_ALPN +#define POLARSSL_SSL_ALPN MBEDTLS_SSL_ALPN +#endif +#if defined MBEDTLS_SSL_CACHE_C +#define POLARSSL_SSL_CACHE_C MBEDTLS_SSL_CACHE_C +#endif +#if defined MBEDTLS_SSL_CBC_RECORD_SPLITTING +#define POLARSSL_SSL_CBC_RECORD_SPLITTING MBEDTLS_SSL_CBC_RECORD_SPLITTING +#endif +#if defined MBEDTLS_SSL_CLI_C +#define POLARSSL_SSL_CLI_C MBEDTLS_SSL_CLI_C +#endif +#if defined MBEDTLS_SSL_COOKIE_C +#define POLARSSL_SSL_COOKIE_C MBEDTLS_SSL_COOKIE_C +#endif +#if defined MBEDTLS_SSL_COOKIE_TIMEOUT +#define POLARSSL_SSL_COOKIE_TIMEOUT MBEDTLS_SSL_COOKIE_TIMEOUT +#endif +#if defined MBEDTLS_SSL_DEBUG_ALL +#define POLARSSL_SSL_DEBUG_ALL MBEDTLS_SSL_DEBUG_ALL +#endif +#if defined MBEDTLS_SSL_DTLS_ANTI_REPLAY +#define POLARSSL_SSL_DTLS_ANTI_REPLAY MBEDTLS_SSL_DTLS_ANTI_REPLAY +#endif +#if defined MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#define POLARSSL_SSL_DTLS_BADMAC_LIMIT MBEDTLS_SSL_DTLS_BADMAC_LIMIT +#endif +#if defined MBEDTLS_SSL_DTLS_HELLO_VERIFY +#define POLARSSL_SSL_DTLS_HELLO_VERIFY MBEDTLS_SSL_DTLS_HELLO_VERIFY +#endif +#if defined MBEDTLS_SSL_ENCRYPT_THEN_MAC +#define POLARSSL_SSL_ENCRYPT_THEN_MAC MBEDTLS_SSL_ENCRYPT_THEN_MAC +#endif +#if defined MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#define POLARSSL_SSL_EXTENDED_MASTER_SECRET MBEDTLS_SSL_EXTENDED_MASTER_SECRET +#endif +#if defined MBEDTLS_SSL_FALLBACK_SCSV +#define POLARSSL_SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#endif +#if defined MBEDTLS_SSL_HW_RECORD_ACCEL +#define POLARSSL_SSL_HW_RECORD_ACCEL MBEDTLS_SSL_HW_RECORD_ACCEL +#endif +#if defined MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH MBEDTLS_SSL_MAX_FRAGMENT_LENGTH +#endif +#if defined MBEDTLS_SSL_PROTO_DTLS +#define POLARSSL_SSL_PROTO_DTLS MBEDTLS_SSL_PROTO_DTLS +#endif +#if defined MBEDTLS_SSL_PROTO_SSL3 +#define POLARSSL_SSL_PROTO_SSL3 MBEDTLS_SSL_PROTO_SSL3 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1 +#define POLARSSL_SSL_PROTO_TLS1 MBEDTLS_SSL_PROTO_TLS1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_1 +#define POLARSSL_SSL_PROTO_TLS1_1 MBEDTLS_SSL_PROTO_TLS1_1 +#endif +#if defined MBEDTLS_SSL_PROTO_TLS1_2 +#define POLARSSL_SSL_PROTO_TLS1_2 MBEDTLS_SSL_PROTO_TLS1_2 +#endif +#if defined MBEDTLS_SSL_RENEGOTIATION +#define POLARSSL_SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#endif +#if defined MBEDTLS_SSL_SERVER_NAME_INDICATION +#define POLARSSL_SSL_SERVER_NAME_INDICATION MBEDTLS_SSL_SERVER_NAME_INDICATION +#endif +#if defined MBEDTLS_SSL_SESSION_TICKETS +#define POLARSSL_SSL_SESSION_TICKETS MBEDTLS_SSL_SESSION_TICKETS +#endif +#if defined MBEDTLS_SSL_SRV_C +#define POLARSSL_SSL_SRV_C MBEDTLS_SSL_SRV_C +#endif +#if defined MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE +#endif +#if defined MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO +#endif +#if defined MBEDTLS_SSL_TLS_C +#define POLARSSL_SSL_TLS_C MBEDTLS_SSL_TLS_C +#endif +#if defined MBEDTLS_SSL_TRUNCATED_HMAC +#define POLARSSL_SSL_TRUNCATED_HMAC MBEDTLS_SSL_TRUNCATED_HMAC +#endif +#if defined MBEDTLS_THREADING_ALT +#define POLARSSL_THREADING_ALT MBEDTLS_THREADING_ALT +#endif +#if defined MBEDTLS_THREADING_C +#define POLARSSL_THREADING_C MBEDTLS_THREADING_C +#endif +#if defined MBEDTLS_THREADING_PTHREAD +#define POLARSSL_THREADING_PTHREAD MBEDTLS_THREADING_PTHREAD +#endif +#if defined MBEDTLS_TIMING_ALT +#define POLARSSL_TIMING_ALT MBEDTLS_TIMING_ALT +#endif +#if defined MBEDTLS_TIMING_C +#define POLARSSL_TIMING_C MBEDTLS_TIMING_C +#endif +#if defined MBEDTLS_VERSION_C +#define POLARSSL_VERSION_C MBEDTLS_VERSION_C +#endif +#if defined MBEDTLS_VERSION_FEATURES +#define POLARSSL_VERSION_FEATURES MBEDTLS_VERSION_FEATURES +#endif +#if defined MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 +#endif +#if defined MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +#endif +#if defined MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CHECK_KEY_USAGE +#define POLARSSL_X509_CHECK_KEY_USAGE MBEDTLS_X509_CHECK_KEY_USAGE +#endif +#if defined MBEDTLS_X509_CREATE_C +#define POLARSSL_X509_CREATE_C MBEDTLS_X509_CREATE_C +#endif +#if defined MBEDTLS_X509_CRL_PARSE_C +#define POLARSSL_X509_CRL_PARSE_C MBEDTLS_X509_CRL_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_PARSE_C +#define POLARSSL_X509_CRT_PARSE_C MBEDTLS_X509_CRT_PARSE_C +#endif +#if defined MBEDTLS_X509_CRT_WRITE_C +#define POLARSSL_X509_CRT_WRITE_C MBEDTLS_X509_CRT_WRITE_C +#endif +#if defined MBEDTLS_X509_CSR_PARSE_C +#define POLARSSL_X509_CSR_PARSE_C MBEDTLS_X509_CSR_PARSE_C +#endif +#if defined MBEDTLS_X509_CSR_WRITE_C +#define POLARSSL_X509_CSR_WRITE_C MBEDTLS_X509_CSR_WRITE_C +#endif +#if defined MBEDTLS_X509_MAX_INTERMEDIATE_CA +#define POLARSSL_X509_MAX_INTERMEDIATE_CA MBEDTLS_X509_MAX_INTERMEDIATE_CA +#endif +#if defined MBEDTLS_X509_RSASSA_PSS_SUPPORT +#define POLARSSL_X509_RSASSA_PSS_SUPPORT MBEDTLS_X509_RSASSA_PSS_SUPPORT +#endif +#if defined MBEDTLS_X509_USE_C +#define POLARSSL_X509_USE_C MBEDTLS_X509_USE_C +#endif +#if defined MBEDTLS_XTEA_ALT +#define POLARSSL_XTEA_ALT MBEDTLS_XTEA_ALT +#endif +#if defined MBEDTLS_XTEA_C +#define POLARSSL_XTEA_C MBEDTLS_XTEA_C +#endif +#if defined MBEDTLS_ZLIB_SUPPORT +#define POLARSSL_ZLIB_SUPPORT MBEDTLS_ZLIB_SUPPORT +#endif + +/* + * Misc names (macros, types, functions, enum constants...) + */ +#define AES_DECRYPT MBEDTLS_AES_DECRYPT +#define AES_ENCRYPT MBEDTLS_AES_ENCRYPT +#define ASN1_BIT_STRING MBEDTLS_ASN1_BIT_STRING +#define ASN1_BMP_STRING MBEDTLS_ASN1_BMP_STRING +#define ASN1_BOOLEAN MBEDTLS_ASN1_BOOLEAN +#define ASN1_CHK_ADD MBEDTLS_ASN1_CHK_ADD +#define ASN1_CONSTRUCTED MBEDTLS_ASN1_CONSTRUCTED +#define ASN1_CONTEXT_SPECIFIC MBEDTLS_ASN1_CONTEXT_SPECIFIC +#define ASN1_GENERALIZED_TIME MBEDTLS_ASN1_GENERALIZED_TIME +#define ASN1_IA5_STRING MBEDTLS_ASN1_IA5_STRING +#define ASN1_INTEGER MBEDTLS_ASN1_INTEGER +#define ASN1_NULL MBEDTLS_ASN1_NULL +#define ASN1_OCTET_STRING MBEDTLS_ASN1_OCTET_STRING +#define ASN1_OID MBEDTLS_ASN1_OID +#define ASN1_PRIMITIVE MBEDTLS_ASN1_PRIMITIVE +#define ASN1_PRINTABLE_STRING MBEDTLS_ASN1_PRINTABLE_STRING +#define ASN1_SEQUENCE MBEDTLS_ASN1_SEQUENCE +#define ASN1_SET MBEDTLS_ASN1_SET +#define ASN1_T61_STRING MBEDTLS_ASN1_T61_STRING +#define ASN1_UNIVERSAL_STRING MBEDTLS_ASN1_UNIVERSAL_STRING +#define ASN1_UTC_TIME MBEDTLS_ASN1_UTC_TIME +#define ASN1_UTF8_STRING MBEDTLS_ASN1_UTF8_STRING +#define BADCERT_CN_MISMATCH MBEDTLS_X509_BADCERT_CN_MISMATCH +#define BADCERT_EXPIRED MBEDTLS_X509_BADCERT_EXPIRED +#define BADCERT_FUTURE MBEDTLS_X509_BADCERT_FUTURE +#define BADCERT_MISSING MBEDTLS_X509_BADCERT_MISSING +#define BADCERT_NOT_TRUSTED MBEDTLS_X509_BADCERT_NOT_TRUSTED +#define BADCERT_OTHER MBEDTLS_X509_BADCERT_OTHER +#define BADCERT_REVOKED MBEDTLS_X509_BADCERT_REVOKED +#define BADCERT_SKIP_VERIFY MBEDTLS_X509_BADCERT_SKIP_VERIFY +#define BADCRL_EXPIRED MBEDTLS_X509_BADCRL_EXPIRED +#define BADCRL_FUTURE MBEDTLS_X509_BADCRL_FUTURE +#define BADCRL_NOT_TRUSTED MBEDTLS_X509_BADCRL_NOT_TRUSTED +#define BLOWFISH_BLOCKSIZE MBEDTLS_BLOWFISH_BLOCKSIZE +#define BLOWFISH_DECRYPT MBEDTLS_BLOWFISH_DECRYPT +#define BLOWFISH_ENCRYPT MBEDTLS_BLOWFISH_ENCRYPT +#define BLOWFISH_MAX_KEY MBEDTLS_BLOWFISH_MAX_KEY_BITS +#define BLOWFISH_MIN_KEY MBEDTLS_BLOWFISH_MIN_KEY_BITS +#define BLOWFISH_ROUNDS MBEDTLS_BLOWFISH_ROUNDS +#define CAMELLIA_DECRYPT MBEDTLS_CAMELLIA_DECRYPT +#define CAMELLIA_ENCRYPT MBEDTLS_CAMELLIA_ENCRYPT +#define COLLECT_SIZE MBEDTLS_HAVEGE_COLLECT_SIZE +#define CTR_DRBG_BLOCKSIZE MBEDTLS_CTR_DRBG_BLOCKSIZE +#define CTR_DRBG_ENTROPY_LEN MBEDTLS_CTR_DRBG_ENTROPY_LEN +#define CTR_DRBG_KEYBITS MBEDTLS_CTR_DRBG_KEYBITS +#define CTR_DRBG_KEYSIZE MBEDTLS_CTR_DRBG_KEYSIZE +#define CTR_DRBG_MAX_INPUT MBEDTLS_CTR_DRBG_MAX_INPUT +#define CTR_DRBG_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST +#define CTR_DRBG_MAX_SEED_INPUT MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +#define CTR_DRBG_PR_OFF MBEDTLS_CTR_DRBG_PR_OFF +#define CTR_DRBG_PR_ON MBEDTLS_CTR_DRBG_PR_ON +#define CTR_DRBG_RESEED_INTERVAL MBEDTLS_CTR_DRBG_RESEED_INTERVAL +#define CTR_DRBG_SEEDLEN MBEDTLS_CTR_DRBG_SEEDLEN +#define DEPRECATED MBEDTLS_DEPRECATED +#define DES_DECRYPT MBEDTLS_DES_DECRYPT +#define DES_ENCRYPT MBEDTLS_DES_ENCRYPT +#define DES_KEY_SIZE MBEDTLS_DES_KEY_SIZE +#define ENTROPY_BLOCK_SIZE MBEDTLS_ENTROPY_BLOCK_SIZE +#define ENTROPY_MAX_GATHER MBEDTLS_ENTROPY_MAX_GATHER +#define ENTROPY_MAX_SEED_SIZE MBEDTLS_ENTROPY_MAX_SEED_SIZE +#define ENTROPY_MAX_SOURCES MBEDTLS_ENTROPY_MAX_SOURCES +#define ENTROPY_MIN_HARDCLOCK MBEDTLS_ENTROPY_MIN_HARDCLOCK +#define ENTROPY_MIN_HAVEGE MBEDTLS_ENTROPY_MIN_HAVEGE +#define ENTROPY_MIN_PLATFORM MBEDTLS_ENTROPY_MIN_PLATFORM +#define ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_SOURCE_MANUAL +#define EXT_AUTHORITY_KEY_IDENTIFIER MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER +#define EXT_BASIC_CONSTRAINTS MBEDTLS_X509_EXT_BASIC_CONSTRAINTS +#define EXT_CERTIFICATE_POLICIES MBEDTLS_X509_EXT_CERTIFICATE_POLICIES +#define EXT_CRL_DISTRIBUTION_POINTS MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS +#define EXT_EXTENDED_KEY_USAGE MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE +#define EXT_FRESHEST_CRL MBEDTLS_X509_EXT_FRESHEST_CRL +#define EXT_INIHIBIT_ANYPOLICY MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY +#define EXT_ISSUER_ALT_NAME MBEDTLS_X509_EXT_ISSUER_ALT_NAME +#define EXT_KEY_USAGE MBEDTLS_X509_EXT_KEY_USAGE +#define EXT_NAME_CONSTRAINTS MBEDTLS_X509_EXT_NAME_CONSTRAINTS +#define EXT_NS_CERT_TYPE MBEDTLS_X509_EXT_NS_CERT_TYPE +#define EXT_POLICY_CONSTRAINTS MBEDTLS_X509_EXT_POLICY_CONSTRAINTS +#define EXT_POLICY_MAPPINGS MBEDTLS_X509_EXT_POLICY_MAPPINGS +#define EXT_SUBJECT_ALT_NAME MBEDTLS_X509_EXT_SUBJECT_ALT_NAME +#define EXT_SUBJECT_DIRECTORY_ATTRS MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS +#define EXT_SUBJECT_KEY_IDENTIFIER MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER +#define GCM_DECRYPT MBEDTLS_GCM_DECRYPT +#define GCM_ENCRYPT MBEDTLS_GCM_ENCRYPT +#define KU_CRL_SIGN MBEDTLS_X509_KU_CRL_SIGN +#define KU_DATA_ENCIPHERMENT MBEDTLS_X509_KU_DATA_ENCIPHERMENT +#define KU_DIGITAL_SIGNATURE MBEDTLS_X509_KU_DIGITAL_SIGNATURE +#define KU_KEY_AGREEMENT MBEDTLS_X509_KU_KEY_AGREEMENT +#define KU_KEY_CERT_SIGN MBEDTLS_X509_KU_KEY_CERT_SIGN +#define KU_KEY_ENCIPHERMENT MBEDTLS_X509_KU_KEY_ENCIPHERMENT +#define KU_NON_REPUDIATION MBEDTLS_X509_KU_NON_REPUDIATION +#define LN_2_DIV_LN_10_SCALE100 MBEDTLS_LN_2_DIV_LN_10_SCALE100 +#define MEMORY_VERIFY_ALLOC MBEDTLS_MEMORY_VERIFY_ALLOC +#define MEMORY_VERIFY_ALWAYS MBEDTLS_MEMORY_VERIFY_ALWAYS +#define MEMORY_VERIFY_FREE MBEDTLS_MEMORY_VERIFY_FREE +#define MEMORY_VERIFY_NONE MBEDTLS_MEMORY_VERIFY_NONE +#define MPI_CHK MBEDTLS_MPI_CHK +#define NET_PROTO_TCP MBEDTLS_NET_PROTO_TCP +#define NET_PROTO_UDP MBEDTLS_NET_PROTO_UDP +#define NS_CERT_TYPE_EMAIL MBEDTLS_X509_NS_CERT_TYPE_EMAIL +#define NS_CERT_TYPE_EMAIL_CA MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA +#define NS_CERT_TYPE_OBJECT_SIGNING MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING +#define NS_CERT_TYPE_OBJECT_SIGNING_CA MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA +#define NS_CERT_TYPE_RESERVED MBEDTLS_X509_NS_CERT_TYPE_RESERVED +#define NS_CERT_TYPE_SSL_CA MBEDTLS_X509_NS_CERT_TYPE_SSL_CA +#define NS_CERT_TYPE_SSL_CLIENT MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT +#define NS_CERT_TYPE_SSL_SERVER MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER +#define OID_ANSI_X9_62 MBEDTLS_OID_ANSI_X9_62 +#define OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE +#define OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD +#define OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62_SIG +#define OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 +#define OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE +#define OID_AT MBEDTLS_OID_AT +#define OID_AT_CN MBEDTLS_OID_AT_CN +#define OID_AT_COUNTRY MBEDTLS_OID_AT_COUNTRY +#define OID_AT_DN_QUALIFIER MBEDTLS_OID_AT_DN_QUALIFIER +#define OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT_GENERATION_QUALIFIER +#define OID_AT_GIVEN_NAME MBEDTLS_OID_AT_GIVEN_NAME +#define OID_AT_INITIALS MBEDTLS_OID_AT_INITIALS +#define OID_AT_LOCALITY MBEDTLS_OID_AT_LOCALITY +#define OID_AT_ORGANIZATION MBEDTLS_OID_AT_ORGANIZATION +#define OID_AT_ORG_UNIT MBEDTLS_OID_AT_ORG_UNIT +#define OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT_POSTAL_ADDRESS +#define OID_AT_POSTAL_CODE MBEDTLS_OID_AT_POSTAL_CODE +#define OID_AT_PSEUDONYM MBEDTLS_OID_AT_PSEUDONYM +#define OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT_SERIAL_NUMBER +#define OID_AT_STATE MBEDTLS_OID_AT_STATE +#define OID_AT_SUR_NAME MBEDTLS_OID_AT_SUR_NAME +#define OID_AT_TITLE MBEDTLS_OID_AT_TITLE +#define OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT_UNIQUE_IDENTIFIER +#define OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER +#define OID_BASIC_CONSTRAINTS MBEDTLS_OID_BASIC_CONSTRAINTS +#define OID_CERTICOM MBEDTLS_OID_CERTICOM +#define OID_CERTIFICATE_POLICIES MBEDTLS_OID_CERTIFICATE_POLICIES +#define OID_CLIENT_AUTH MBEDTLS_OID_CLIENT_AUTH +#define OID_CMP MBEDTLS_OID_CMP +#define OID_CODE_SIGNING MBEDTLS_OID_CODE_SIGNING +#define OID_COUNTRY_US MBEDTLS_OID_COUNTRY_US +#define OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_CRL_DISTRIBUTION_POINTS +#define OID_CRL_NUMBER MBEDTLS_OID_CRL_NUMBER +#define OID_DES_CBC MBEDTLS_OID_DES_CBC +#define OID_DES_EDE3_CBC MBEDTLS_OID_DES_EDE3_CBC +#define OID_DIGEST_ALG_MD2 MBEDTLS_OID_DIGEST_ALG_MD2 +#define OID_DIGEST_ALG_MD4 MBEDTLS_OID_DIGEST_ALG_MD4 +#define OID_DIGEST_ALG_MD5 MBEDTLS_OID_DIGEST_ALG_MD5 +#define OID_DIGEST_ALG_SHA1 MBEDTLS_OID_DIGEST_ALG_SHA1 +#define OID_DIGEST_ALG_SHA224 MBEDTLS_OID_DIGEST_ALG_SHA224 +#define OID_DIGEST_ALG_SHA256 MBEDTLS_OID_DIGEST_ALG_SHA256 +#define OID_DIGEST_ALG_SHA384 MBEDTLS_OID_DIGEST_ALG_SHA384 +#define OID_DIGEST_ALG_SHA512 MBEDTLS_OID_DIGEST_ALG_SHA512 +#define OID_DOMAIN_COMPONENT MBEDTLS_OID_DOMAIN_COMPONENT +#define OID_ECDSA_SHA1 MBEDTLS_OID_ECDSA_SHA1 +#define OID_ECDSA_SHA224 MBEDTLS_OID_ECDSA_SHA224 +#define OID_ECDSA_SHA256 MBEDTLS_OID_ECDSA_SHA256 +#define OID_ECDSA_SHA384 MBEDTLS_OID_ECDSA_SHA384 +#define OID_ECDSA_SHA512 MBEDTLS_OID_ECDSA_SHA512 +#define OID_EC_ALG_ECDH MBEDTLS_OID_EC_ALG_ECDH +#define OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_EC_ALG_UNRESTRICTED +#define OID_EC_BRAINPOOL_V1 MBEDTLS_OID_EC_BRAINPOOL_V1 +#define OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_GRP_BP256R1 +#define OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_GRP_BP384R1 +#define OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_GRP_BP512R1 +#define OID_EC_GRP_SECP192K1 MBEDTLS_OID_EC_GRP_SECP192K1 +#define OID_EC_GRP_SECP192R1 MBEDTLS_OID_EC_GRP_SECP192R1 +#define OID_EC_GRP_SECP224K1 MBEDTLS_OID_EC_GRP_SECP224K1 +#define OID_EC_GRP_SECP224R1 MBEDTLS_OID_EC_GRP_SECP224R1 +#define OID_EC_GRP_SECP256K1 MBEDTLS_OID_EC_GRP_SECP256K1 +#define OID_EC_GRP_SECP256R1 MBEDTLS_OID_EC_GRP_SECP256R1 +#define OID_EC_GRP_SECP384R1 MBEDTLS_OID_EC_GRP_SECP384R1 +#define OID_EC_GRP_SECP521R1 MBEDTLS_OID_EC_GRP_SECP521R1 +#define OID_EMAIL_PROTECTION MBEDTLS_OID_EMAIL_PROTECTION +#define OID_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE +#define OID_FRESHEST_CRL MBEDTLS_OID_FRESHEST_CRL +#define OID_GOV MBEDTLS_OID_GOV +#define OID_HMAC_SHA1 MBEDTLS_OID_HMAC_SHA1 +#define OID_ID_CE MBEDTLS_OID_ID_CE +#define OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_INIHIBIT_ANYPOLICY +#define OID_ISO_CCITT_DS MBEDTLS_OID_ISO_CCITT_DS +#define OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ISO_IDENTIFIED_ORG +#define OID_ISO_ITU_COUNTRY MBEDTLS_OID_ISO_ITU_COUNTRY +#define OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_US_ORG +#define OID_ISO_MEMBER_BODIES MBEDTLS_OID_ISO_MEMBER_BODIES +#define OID_ISSUER_ALT_NAME MBEDTLS_OID_ISSUER_ALT_NAME +#define OID_KEY_USAGE MBEDTLS_OID_KEY_USAGE +#define OID_KP MBEDTLS_OID_KP +#define OID_MGF1 MBEDTLS_OID_MGF1 +#define OID_NAME_CONSTRAINTS MBEDTLS_OID_NAME_CONSTRAINTS +#define OID_NETSCAPE MBEDTLS_OID_NETSCAPE +#define OID_NS_BASE_URL MBEDTLS_OID_NS_BASE_URL +#define OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CA_POLICY_URL +#define OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CA_REVOCATION_URL +#define OID_NS_CERT MBEDTLS_OID_NS_CERT +#define OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_CERT_SEQUENCE +#define OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT_TYPE +#define OID_NS_COMMENT MBEDTLS_OID_NS_COMMENT +#define OID_NS_DATA_TYPE MBEDTLS_OID_NS_DATA_TYPE +#define OID_NS_RENEWAL_URL MBEDTLS_OID_NS_RENEWAL_URL +#define OID_NS_REVOCATION_URL MBEDTLS_OID_NS_REVOCATION_URL +#define OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_SSL_SERVER_NAME +#define OID_OCSP_SIGNING MBEDTLS_OID_OCSP_SIGNING +#define OID_OIW_SECSIG MBEDTLS_OID_OIW_SECSIG +#define OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG_ALG +#define OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_SHA1 +#define OID_ORGANIZATION MBEDTLS_OID_ORGANIZATION +#define OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62 +#define OID_ORG_CERTICOM MBEDTLS_OID_ORG_CERTICOM +#define OID_ORG_DOD MBEDTLS_OID_ORG_DOD +#define OID_ORG_GOV MBEDTLS_OID_ORG_GOV +#define OID_ORG_NETSCAPE MBEDTLS_OID_ORG_NETSCAPE +#define OID_ORG_OIW MBEDTLS_OID_ORG_OIW +#define OID_ORG_RSA_DATA_SECURITY MBEDTLS_OID_ORG_RSA_DATA_SECURITY +#define OID_ORG_TELETRUST MBEDTLS_OID_ORG_TELETRUST +#define OID_PKCS MBEDTLS_OID_PKCS +#define OID_PKCS1 MBEDTLS_OID_PKCS1 +#define OID_PKCS12 MBEDTLS_OID_PKCS12 +#define OID_PKCS12_PBE MBEDTLS_OID_PKCS12_PBE +#define OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC +#define OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC +#define OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC +#define OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC +#define OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 +#define OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 +#define OID_PKCS1_MD2 MBEDTLS_OID_PKCS1_MD2 +#define OID_PKCS1_MD4 MBEDTLS_OID_PKCS1_MD4 +#define OID_PKCS1_MD5 MBEDTLS_OID_PKCS1_MD5 +#define OID_PKCS1_RSA MBEDTLS_OID_PKCS1_RSA +#define OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1_SHA1 +#define OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1_SHA224 +#define OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1_SHA256 +#define OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1_SHA384 +#define OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1_SHA512 +#define OID_PKCS5 MBEDTLS_OID_PKCS5 +#define OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5_PBES2 +#define OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC +#define OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC +#define OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC +#define OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC +#define OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC +#define OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC +#define OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5_PBKDF2 +#define OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5_PBMAC1 +#define OID_PKCS9 MBEDTLS_OID_PKCS9 +#define OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9_CSR_EXT_REQ +#define OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9_EMAIL +#define OID_PKIX MBEDTLS_OID_PKIX +#define OID_POLICY_CONSTRAINTS MBEDTLS_OID_POLICY_CONSTRAINTS +#define OID_POLICY_MAPPINGS MBEDTLS_OID_POLICY_MAPPINGS +#define OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD +#define OID_RSASSA_PSS MBEDTLS_OID_RSASSA_PSS +#define OID_RSA_COMPANY MBEDTLS_OID_RSA_COMPANY +#define OID_RSA_SHA_OBS MBEDTLS_OID_RSA_SHA_OBS +#define OID_SERVER_AUTH MBEDTLS_OID_SERVER_AUTH +#define OID_SIZE MBEDTLS_OID_SIZE +#define OID_SUBJECT_ALT_NAME MBEDTLS_OID_SUBJECT_ALT_NAME +#define OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS +#define OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER +#define OID_TELETRUST MBEDTLS_OID_TELETRUST +#define OID_TIME_STAMPING MBEDTLS_OID_TIME_STAMPING +#define PADLOCK_ACE MBEDTLS_PADLOCK_ACE +#define PADLOCK_ALIGN16 MBEDTLS_PADLOCK_ALIGN16 +#define PADLOCK_PHE MBEDTLS_PADLOCK_PHE +#define PADLOCK_PMM MBEDTLS_PADLOCK_PMM +#define PADLOCK_RNG MBEDTLS_PADLOCK_RNG +#define PKCS12_DERIVE_IV MBEDTLS_PKCS12_DERIVE_IV +#define PKCS12_DERIVE_KEY MBEDTLS_PKCS12_DERIVE_KEY +#define PKCS12_DERIVE_MAC_KEY MBEDTLS_PKCS12_DERIVE_MAC_KEY +#define PKCS12_PBE_DECRYPT MBEDTLS_PKCS12_PBE_DECRYPT +#define PKCS12_PBE_ENCRYPT MBEDTLS_PKCS12_PBE_ENCRYPT +#define PKCS5_DECRYPT MBEDTLS_PKCS5_DECRYPT +#define PKCS5_ENCRYPT MBEDTLS_PKCS5_ENCRYPT +#define POLARSSL_AESNI_AES MBEDTLS_AESNI_AES +#define POLARSSL_AESNI_CLMUL MBEDTLS_AESNI_CLMUL +#define POLARSSL_AESNI_H MBEDTLS_AESNI_H +#define POLARSSL_AES_H MBEDTLS_AES_H +#define POLARSSL_ARC4_H MBEDTLS_ARC4_H +#define POLARSSL_ASN1_H MBEDTLS_ASN1_H +#define POLARSSL_ASN1_WRITE_H MBEDTLS_ASN1_WRITE_H +#define POLARSSL_BASE64_H MBEDTLS_BASE64_H +#define POLARSSL_BIGNUM_H MBEDTLS_BIGNUM_H +#define POLARSSL_BLOWFISH_H MBEDTLS_BLOWFISH_H +#define POLARSSL_BN_MUL_H MBEDTLS_BN_MUL_H +#define POLARSSL_CAMELLIA_H MBEDTLS_CAMELLIA_H +#define POLARSSL_CCM_H MBEDTLS_CCM_H +#define POLARSSL_CERTS_H MBEDTLS_CERTS_H +#define POLARSSL_CHECK_CONFIG_H MBEDTLS_CHECK_CONFIG_H +#define POLARSSL_CIPHERSUITE_NODTLS MBEDTLS_CIPHERSUITE_NODTLS +#define POLARSSL_CIPHERSUITE_SHORT_TAG MBEDTLS_CIPHERSUITE_SHORT_TAG +#define POLARSSL_CIPHERSUITE_WEAK MBEDTLS_CIPHERSUITE_WEAK +#define POLARSSL_CIPHER_AES_128_CBC MBEDTLS_CIPHER_AES_128_CBC +#define POLARSSL_CIPHER_AES_128_CCM MBEDTLS_CIPHER_AES_128_CCM +#define POLARSSL_CIPHER_AES_128_CFB128 MBEDTLS_CIPHER_AES_128_CFB128 +#define POLARSSL_CIPHER_AES_128_CTR MBEDTLS_CIPHER_AES_128_CTR +#define POLARSSL_CIPHER_AES_128_ECB MBEDTLS_CIPHER_AES_128_ECB +#define POLARSSL_CIPHER_AES_128_GCM MBEDTLS_CIPHER_AES_128_GCM +#define POLARSSL_CIPHER_AES_192_CBC MBEDTLS_CIPHER_AES_192_CBC +#define POLARSSL_CIPHER_AES_192_CCM MBEDTLS_CIPHER_AES_192_CCM +#define POLARSSL_CIPHER_AES_192_CFB128 MBEDTLS_CIPHER_AES_192_CFB128 +#define POLARSSL_CIPHER_AES_192_CTR MBEDTLS_CIPHER_AES_192_CTR +#define POLARSSL_CIPHER_AES_192_ECB MBEDTLS_CIPHER_AES_192_ECB +#define POLARSSL_CIPHER_AES_192_GCM MBEDTLS_CIPHER_AES_192_GCM +#define POLARSSL_CIPHER_AES_256_CBC MBEDTLS_CIPHER_AES_256_CBC +#define POLARSSL_CIPHER_AES_256_CCM MBEDTLS_CIPHER_AES_256_CCM +#define POLARSSL_CIPHER_AES_256_CFB128 MBEDTLS_CIPHER_AES_256_CFB128 +#define POLARSSL_CIPHER_AES_256_CTR MBEDTLS_CIPHER_AES_256_CTR +#define POLARSSL_CIPHER_AES_256_ECB MBEDTLS_CIPHER_AES_256_ECB +#define POLARSSL_CIPHER_AES_256_GCM MBEDTLS_CIPHER_AES_256_GCM +#define POLARSSL_CIPHER_ARC4_128 MBEDTLS_CIPHER_ARC4_128 +#define POLARSSL_CIPHER_BLOWFISH_CBC MBEDTLS_CIPHER_BLOWFISH_CBC +#define POLARSSL_CIPHER_BLOWFISH_CFB64 MBEDTLS_CIPHER_BLOWFISH_CFB64 +#define POLARSSL_CIPHER_BLOWFISH_CTR MBEDTLS_CIPHER_BLOWFISH_CTR +#define POLARSSL_CIPHER_BLOWFISH_ECB MBEDTLS_CIPHER_BLOWFISH_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_CBC MBEDTLS_CIPHER_CAMELLIA_128_CBC +#define POLARSSL_CIPHER_CAMELLIA_128_CCM MBEDTLS_CIPHER_CAMELLIA_128_CCM +#define POLARSSL_CIPHER_CAMELLIA_128_CFB128 MBEDTLS_CIPHER_CAMELLIA_128_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_128_CTR MBEDTLS_CIPHER_CAMELLIA_128_CTR +#define POLARSSL_CIPHER_CAMELLIA_128_ECB MBEDTLS_CIPHER_CAMELLIA_128_ECB +#define POLARSSL_CIPHER_CAMELLIA_128_GCM MBEDTLS_CIPHER_CAMELLIA_128_GCM +#define POLARSSL_CIPHER_CAMELLIA_192_CBC MBEDTLS_CIPHER_CAMELLIA_192_CBC +#define POLARSSL_CIPHER_CAMELLIA_192_CCM MBEDTLS_CIPHER_CAMELLIA_192_CCM +#define POLARSSL_CIPHER_CAMELLIA_192_CFB128 MBEDTLS_CIPHER_CAMELLIA_192_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_192_CTR MBEDTLS_CIPHER_CAMELLIA_192_CTR +#define POLARSSL_CIPHER_CAMELLIA_192_ECB MBEDTLS_CIPHER_CAMELLIA_192_ECB +#define POLARSSL_CIPHER_CAMELLIA_192_GCM MBEDTLS_CIPHER_CAMELLIA_192_GCM +#define POLARSSL_CIPHER_CAMELLIA_256_CBC MBEDTLS_CIPHER_CAMELLIA_256_CBC +#define POLARSSL_CIPHER_CAMELLIA_256_CCM MBEDTLS_CIPHER_CAMELLIA_256_CCM +#define POLARSSL_CIPHER_CAMELLIA_256_CFB128 MBEDTLS_CIPHER_CAMELLIA_256_CFB128 +#define POLARSSL_CIPHER_CAMELLIA_256_CTR MBEDTLS_CIPHER_CAMELLIA_256_CTR +#define POLARSSL_CIPHER_CAMELLIA_256_ECB MBEDTLS_CIPHER_CAMELLIA_256_ECB +#define POLARSSL_CIPHER_CAMELLIA_256_GCM MBEDTLS_CIPHER_CAMELLIA_256_GCM +#define POLARSSL_CIPHER_DES_CBC MBEDTLS_CIPHER_DES_CBC +#define POLARSSL_CIPHER_DES_ECB MBEDTLS_CIPHER_DES_ECB +#define POLARSSL_CIPHER_DES_EDE3_CBC MBEDTLS_CIPHER_DES_EDE3_CBC +#define POLARSSL_CIPHER_DES_EDE3_ECB MBEDTLS_CIPHER_DES_EDE3_ECB +#define POLARSSL_CIPHER_DES_EDE_CBC MBEDTLS_CIPHER_DES_EDE_CBC +#define POLARSSL_CIPHER_DES_EDE_ECB MBEDTLS_CIPHER_DES_EDE_ECB +#define POLARSSL_CIPHER_H MBEDTLS_CIPHER_H +#define POLARSSL_CIPHER_ID_3DES MBEDTLS_CIPHER_ID_3DES +#define POLARSSL_CIPHER_ID_AES MBEDTLS_CIPHER_ID_AES +#define POLARSSL_CIPHER_ID_ARC4 MBEDTLS_CIPHER_ID_ARC4 +#define POLARSSL_CIPHER_ID_BLOWFISH MBEDTLS_CIPHER_ID_BLOWFISH +#define POLARSSL_CIPHER_ID_CAMELLIA MBEDTLS_CIPHER_ID_CAMELLIA +#define POLARSSL_CIPHER_ID_DES MBEDTLS_CIPHER_ID_DES +#define POLARSSL_CIPHER_ID_NONE MBEDTLS_CIPHER_ID_NONE +#define POLARSSL_CIPHER_ID_NULL MBEDTLS_CIPHER_ID_NULL +#define POLARSSL_CIPHER_MODE_AEAD MBEDTLS_CIPHER_MODE_AEAD +#define POLARSSL_CIPHER_MODE_STREAM MBEDTLS_CIPHER_MODE_STREAM +#define POLARSSL_CIPHER_MODE_WITH_PADDING MBEDTLS_CIPHER_MODE_WITH_PADDING +#define POLARSSL_CIPHER_NONE MBEDTLS_CIPHER_NONE +#define POLARSSL_CIPHER_NULL MBEDTLS_CIPHER_NULL +#define POLARSSL_CIPHER_VARIABLE_IV_LEN MBEDTLS_CIPHER_VARIABLE_IV_LEN +#define POLARSSL_CIPHER_VARIABLE_KEY_LEN MBEDTLS_CIPHER_VARIABLE_KEY_LEN +#define POLARSSL_CIPHER_WRAP_H MBEDTLS_CIPHER_WRAP_H +#define POLARSSL_CONFIG_H MBEDTLS_CONFIG_H +#define POLARSSL_CTR_DRBG_H MBEDTLS_CTR_DRBG_H +#define POLARSSL_DEBUG_H MBEDTLS_DEBUG_H +#define POLARSSL_DECRYPT MBEDTLS_DECRYPT +#define POLARSSL_DES_H MBEDTLS_DES_H +#define POLARSSL_DHM_H MBEDTLS_DHM_H +#define POLARSSL_DHM_RFC3526_MODP_2048_G MBEDTLS_DHM_RFC3526_MODP_2048_G +#define POLARSSL_DHM_RFC3526_MODP_2048_P MBEDTLS_DHM_RFC3526_MODP_2048_P +#define POLARSSL_DHM_RFC3526_MODP_3072_G MBEDTLS_DHM_RFC3526_MODP_3072_G +#define POLARSSL_DHM_RFC3526_MODP_3072_P MBEDTLS_DHM_RFC3526_MODP_3072_P +#define POLARSSL_DHM_RFC5114_MODP_2048_G MBEDTLS_DHM_RFC5114_MODP_2048_G +#define POLARSSL_DHM_RFC5114_MODP_2048_P MBEDTLS_DHM_RFC5114_MODP_2048_P +#define POLARSSL_ECDH_H MBEDTLS_ECDH_H +#define POLARSSL_ECDH_OURS MBEDTLS_ECDH_OURS +#define POLARSSL_ECDH_THEIRS MBEDTLS_ECDH_THEIRS +#define POLARSSL_ECDSA_H MBEDTLS_ECDSA_H +#define POLARSSL_ECP_DP_BP256R1 MBEDTLS_ECP_DP_BP256R1 +#define POLARSSL_ECP_DP_BP384R1 MBEDTLS_ECP_DP_BP384R1 +#define POLARSSL_ECP_DP_BP512R1 MBEDTLS_ECP_DP_BP512R1 +#define POLARSSL_ECP_DP_M255 MBEDTLS_ECP_DP_CURVE25519 +#define POLARSSL_ECP_DP_MAX MBEDTLS_ECP_DP_MAX +#define POLARSSL_ECP_DP_NONE MBEDTLS_ECP_DP_NONE +#define POLARSSL_ECP_DP_SECP192K1 MBEDTLS_ECP_DP_SECP192K1 +#define POLARSSL_ECP_DP_SECP192R1 MBEDTLS_ECP_DP_SECP192R1 +#define POLARSSL_ECP_DP_SECP224K1 MBEDTLS_ECP_DP_SECP224K1 +#define POLARSSL_ECP_DP_SECP224R1 MBEDTLS_ECP_DP_SECP224R1 +#define POLARSSL_ECP_DP_SECP256K1 MBEDTLS_ECP_DP_SECP256K1 +#define POLARSSL_ECP_DP_SECP256R1 MBEDTLS_ECP_DP_SECP256R1 +#define POLARSSL_ECP_DP_SECP384R1 MBEDTLS_ECP_DP_SECP384R1 +#define POLARSSL_ECP_DP_SECP521R1 MBEDTLS_ECP_DP_SECP521R1 +#define POLARSSL_ECP_H MBEDTLS_ECP_H +#define POLARSSL_ECP_MAX_BYTES MBEDTLS_ECP_MAX_BYTES +#define POLARSSL_ECP_MAX_PT_LEN MBEDTLS_ECP_MAX_PT_LEN +#define POLARSSL_ECP_PF_COMPRESSED MBEDTLS_ECP_PF_COMPRESSED +#define POLARSSL_ECP_PF_UNCOMPRESSED MBEDTLS_ECP_PF_UNCOMPRESSED +#define POLARSSL_ECP_TLS_NAMED_CURVE MBEDTLS_ECP_TLS_NAMED_CURVE +#define POLARSSL_ENCRYPT MBEDTLS_ENCRYPT +#define POLARSSL_ENTROPY_H MBEDTLS_ENTROPY_H +#define POLARSSL_ENTROPY_POLL_H MBEDTLS_ENTROPY_POLL_H +#define POLARSSL_ENTROPY_SHA256_ACCUMULATOR MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#define POLARSSL_ENTROPY_SHA512_ACCUMULATOR MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#define POLARSSL_ERROR_H MBEDTLS_ERROR_H +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH MBEDTLS_ERR_AES_INVALID_KEY_LENGTH +#define POLARSSL_ERR_ASN1_BUF_TOO_SMALL MBEDTLS_ERR_ASN1_BUF_TOO_SMALL +#define POLARSSL_ERR_ASN1_INVALID_DATA MBEDTLS_ERR_ASN1_INVALID_DATA +#define POLARSSL_ERR_ASN1_INVALID_LENGTH MBEDTLS_ERR_ASN1_INVALID_LENGTH +#define POLARSSL_ERR_ASN1_LENGTH_MISMATCH MBEDTLS_ERR_ASN1_LENGTH_MISMATCH +#define POLARSSL_ERR_ASN1_MALLOC_FAILED MBEDTLS_ERR_ASN1_ALLOC_FAILED +#define POLARSSL_ERR_ASN1_OUT_OF_DATA MBEDTLS_ERR_ASN1_OUT_OF_DATA +#define POLARSSL_ERR_ASN1_UNEXPECTED_TAG MBEDTLS_ERR_ASN1_UNEXPECTED_TAG +#define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL +#define POLARSSL_ERR_BASE64_INVALID_CHARACTER MBEDTLS_ERR_BASE64_INVALID_CHARACTER +#define POLARSSL_ERR_BLOWFISH_INVALID_INPUT_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_INPUT_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH +#define POLARSSL_ERR_CCM_AUTH_FAILED MBEDTLS_ERR_CCM_AUTH_FAILED +#define POLARSSL_ERR_CCM_BAD_INPUT MBEDTLS_ERR_CCM_BAD_INPUT +#define POLARSSL_ERR_CIPHER_ALLOC_FAILED MBEDTLS_ERR_CIPHER_ALLOC_FAILED +#define POLARSSL_ERR_CIPHER_AUTH_FAILED MBEDTLS_ERR_CIPHER_AUTH_FAILED +#define POLARSSL_ERR_CIPHER_BAD_INPUT_DATA MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA +#define POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED +#define POLARSSL_ERR_CIPHER_INVALID_PADDING MBEDTLS_ERR_CIPHER_INVALID_PADDING +#define POLARSSL_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_CTR_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH +#define POLARSSL_ERR_DHM_BAD_INPUT_DATA MBEDTLS_ERR_DHM_BAD_INPUT_DATA +#define POLARSSL_ERR_DHM_CALC_SECRET_FAILED MBEDTLS_ERR_DHM_CALC_SECRET_FAILED +#define POLARSSL_ERR_DHM_FILE_IO_ERROR MBEDTLS_ERR_DHM_FILE_IO_ERROR +#define POLARSSL_ERR_DHM_INVALID_FORMAT MBEDTLS_ERR_DHM_INVALID_FORMAT +#define POLARSSL_ERR_DHM_MAKE_PARAMS_FAILED MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED +#define POLARSSL_ERR_DHM_MAKE_PUBLIC_FAILED MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED +#define POLARSSL_ERR_DHM_MALLOC_FAILED MBEDTLS_ERR_DHM_ALLOC_FAILED +#define POLARSSL_ERR_DHM_READ_PARAMS_FAILED MBEDTLS_ERR_DHM_READ_PARAMS_FAILED +#define POLARSSL_ERR_DHM_READ_PUBLIC_FAILED MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED +#define POLARSSL_ERR_ECP_BAD_INPUT_DATA MBEDTLS_ERR_ECP_BAD_INPUT_DATA +#define POLARSSL_ERR_ECP_BUFFER_TOO_SMALL MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL +#define POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_ECP_INVALID_KEY MBEDTLS_ERR_ECP_INVALID_KEY +#define POLARSSL_ERR_ECP_MALLOC_FAILED MBEDTLS_ERR_ECP_ALLOC_FAILED +#define POLARSSL_ERR_ECP_RANDOM_FAILED MBEDTLS_ERR_ECP_RANDOM_FAILED +#define POLARSSL_ERR_ECP_SIG_LEN_MISMATCH MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH +#define POLARSSL_ERR_ECP_VERIFY_FAILED MBEDTLS_ERR_ECP_VERIFY_FAILED +#define POLARSSL_ERR_ENTROPY_FILE_IO_ERROR MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR +#define POLARSSL_ERR_ENTROPY_MAX_SOURCES MBEDTLS_ERR_ENTROPY_MAX_SOURCES +#define POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED +#define POLARSSL_ERR_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_GCM_AUTH_FAILED MBEDTLS_ERR_GCM_AUTH_FAILED +#define POLARSSL_ERR_GCM_BAD_INPUT MBEDTLS_ERR_GCM_BAD_INPUT +#define POLARSSL_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED +#define POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR +#define POLARSSL_ERR_HMAC_DRBG_INPUT_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG +#define POLARSSL_ERR_HMAC_DRBG_REQUEST_TOO_BIG MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG +#define POLARSSL_ERR_MD_ALLOC_FAILED MBEDTLS_ERR_MD_ALLOC_FAILED +#define POLARSSL_ERR_MD_BAD_INPUT_DATA MBEDTLS_ERR_MD_BAD_INPUT_DATA +#define POLARSSL_ERR_MD_FEATURE_UNAVAILABLE MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_MD_FILE_IO_ERROR MBEDTLS_ERR_MD_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_BAD_INPUT_DATA MBEDTLS_ERR_MPI_BAD_INPUT_DATA +#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL +#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO MBEDTLS_ERR_MPI_DIVISION_BY_ZERO +#define POLARSSL_ERR_MPI_FILE_IO_ERROR MBEDTLS_ERR_MPI_FILE_IO_ERROR +#define POLARSSL_ERR_MPI_INVALID_CHARACTER MBEDTLS_ERR_MPI_INVALID_CHARACTER +#define POLARSSL_ERR_MPI_MALLOC_FAILED MBEDTLS_ERR_MPI_ALLOC_FAILED +#define POLARSSL_ERR_MPI_NEGATIVE_VALUE MBEDTLS_ERR_MPI_NEGATIVE_VALUE +#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE MBEDTLS_ERR_MPI_NOT_ACCEPTABLE +#define POLARSSL_ERR_NET_ACCEPT_FAILED MBEDTLS_ERR_NET_ACCEPT_FAILED +#define POLARSSL_ERR_NET_BIND_FAILED MBEDTLS_ERR_NET_BIND_FAILED +#define POLARSSL_ERR_NET_CONNECT_FAILED MBEDTLS_ERR_NET_CONNECT_FAILED +#define POLARSSL_ERR_NET_CONN_RESET MBEDTLS_ERR_NET_CONN_RESET +#define POLARSSL_ERR_NET_LISTEN_FAILED MBEDTLS_ERR_NET_LISTEN_FAILED +#define POLARSSL_ERR_NET_RECV_FAILED MBEDTLS_ERR_NET_RECV_FAILED +#define POLARSSL_ERR_NET_SEND_FAILED MBEDTLS_ERR_NET_SEND_FAILED +#define POLARSSL_ERR_NET_SOCKET_FAILED MBEDTLS_ERR_NET_SOCKET_FAILED +#define POLARSSL_ERR_NET_TIMEOUT MBEDTLS_ERR_SSL_TIMEOUT +#define POLARSSL_ERR_NET_UNKNOWN_HOST MBEDTLS_ERR_NET_UNKNOWN_HOST +#define POLARSSL_ERR_NET_WANT_READ MBEDTLS_ERR_SSL_WANT_READ +#define POLARSSL_ERR_NET_WANT_WRITE MBEDTLS_ERR_SSL_WANT_WRITE +#define POLARSSL_ERR_OID_BUF_TOO_SMALL MBEDTLS_ERR_OID_BUF_TOO_SMALL +#define POLARSSL_ERR_OID_NOT_FOUND MBEDTLS_ERR_OID_NOT_FOUND +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED +#define POLARSSL_ERR_PEM_BAD_INPUT_DATA MBEDTLS_ERR_PEM_BAD_INPUT_DATA +#define POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PEM_INVALID_DATA MBEDTLS_ERR_PEM_INVALID_DATA +#define POLARSSL_ERR_PEM_INVALID_ENC_IV MBEDTLS_ERR_PEM_INVALID_ENC_IV +#define POLARSSL_ERR_PEM_MALLOC_FAILED MBEDTLS_ERR_PEM_ALLOC_FAILED +#define POLARSSL_ERR_PEM_NO_HEADER_FOOTER_PRESENT MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT +#define POLARSSL_ERR_PEM_PASSWORD_MISMATCH MBEDTLS_ERR_PEM_PASSWORD_MISMATCH +#define POLARSSL_ERR_PEM_PASSWORD_REQUIRED MBEDTLS_ERR_PEM_PASSWORD_REQUIRED +#define POLARSSL_ERR_PEM_UNKNOWN_ENC_ALG MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG +#define POLARSSL_ERR_PKCS12_BAD_INPUT_DATA MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS12_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH +#define POLARSSL_ERR_PKCS12_PBE_INVALID_FORMAT MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_BAD_INPUT_DATA MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA +#define POLARSSL_ERR_PKCS5_FEATURE_UNAVAILABLE MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PKCS5_INVALID_FORMAT MBEDTLS_ERR_PKCS5_INVALID_FORMAT +#define POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_BAD_INPUT_DATA MBEDTLS_ERR_PK_BAD_INPUT_DATA +#define POLARSSL_ERR_PK_FEATURE_UNAVAILABLE MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_PK_FILE_IO_ERROR MBEDTLS_ERR_PK_FILE_IO_ERROR +#define POLARSSL_ERR_PK_INVALID_ALG MBEDTLS_ERR_PK_INVALID_ALG +#define POLARSSL_ERR_PK_INVALID_PUBKEY MBEDTLS_ERR_PK_INVALID_PUBKEY +#define POLARSSL_ERR_PK_KEY_INVALID_FORMAT MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +#define POLARSSL_ERR_PK_KEY_INVALID_VERSION MBEDTLS_ERR_PK_KEY_INVALID_VERSION +#define POLARSSL_ERR_PK_MALLOC_FAILED MBEDTLS_ERR_PK_ALLOC_FAILED +#define POLARSSL_ERR_PK_PASSWORD_MISMATCH MBEDTLS_ERR_PK_PASSWORD_MISMATCH +#define POLARSSL_ERR_PK_PASSWORD_REQUIRED MBEDTLS_ERR_PK_PASSWORD_REQUIRED +#define POLARSSL_ERR_PK_SIG_LEN_MISMATCH MBEDTLS_ERR_PK_SIG_LEN_MISMATCH +#define POLARSSL_ERR_PK_TYPE_MISMATCH MBEDTLS_ERR_PK_TYPE_MISMATCH +#define POLARSSL_ERR_PK_UNKNOWN_NAMED_CURVE MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE +#define POLARSSL_ERR_PK_UNKNOWN_PK_ALG MBEDTLS_ERR_PK_UNKNOWN_PK_ALG +#define POLARSSL_ERR_RSA_BAD_INPUT_DATA MBEDTLS_ERR_RSA_BAD_INPUT_DATA +#define POLARSSL_ERR_RSA_INVALID_PADDING MBEDTLS_ERR_RSA_INVALID_PADDING +#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED MBEDTLS_ERR_RSA_KEY_CHECK_FAILED +#define POLARSSL_ERR_RSA_KEY_GEN_FAILED MBEDTLS_ERR_RSA_KEY_GEN_FAILED +#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE +#define POLARSSL_ERR_RSA_PRIVATE_FAILED MBEDTLS_ERR_RSA_PRIVATE_FAILED +#define POLARSSL_ERR_RSA_PUBLIC_FAILED MBEDTLS_ERR_RSA_PUBLIC_FAILED +#define POLARSSL_ERR_RSA_RNG_FAILED MBEDTLS_ERR_RSA_RNG_FAILED +#define POLARSSL_ERR_RSA_VERIFY_FAILED MBEDTLS_ERR_RSA_VERIFY_FAILED +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST +#define POLARSSL_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY +#define POLARSSL_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS +#define POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP +#define POLARSSL_ERR_SSL_BAD_HS_FINISHED MBEDTLS_ERR_SSL_BAD_HS_FINISHED +#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET +#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_HELLO_DONE MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE +#define POLARSSL_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE +#define POLARSSL_ERR_SSL_BAD_INPUT_DATA MBEDTLS_ERR_SSL_BAD_INPUT_DATA +#define POLARSSL_ERR_SSL_BUFFER_TOO_SMALL MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL +#define POLARSSL_ERR_SSL_CA_CHAIN_REQUIRED MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_REQUIRED MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED +#define POLARSSL_ERR_SSL_CERTIFICATE_TOO_LARGE MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE +#define POLARSSL_ERR_SSL_COMPRESSION_FAILED MBEDTLS_ERR_SSL_COMPRESSION_FAILED +#define POLARSSL_ERR_SSL_CONN_EOF MBEDTLS_ERR_SSL_CONN_EOF +#define POLARSSL_ERR_SSL_COUNTER_WRAPPING MBEDTLS_ERR_SSL_COUNTER_WRAPPING +#define POLARSSL_ERR_SSL_FATAL_ALERT_MESSAGE MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE +#define POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED +#define POLARSSL_ERR_SSL_HW_ACCEL_FAILED MBEDTLS_ERR_SSL_HW_ACCEL_FAILED +#define POLARSSL_ERR_SSL_HW_ACCEL_FALLTHROUGH MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH +#define POLARSSL_ERR_SSL_INTERNAL_ERROR MBEDTLS_ERR_SSL_INTERNAL_ERROR +#define POLARSSL_ERR_SSL_INVALID_MAC MBEDTLS_ERR_SSL_INVALID_MAC +#define POLARSSL_ERR_SSL_INVALID_RECORD MBEDTLS_ERR_SSL_INVALID_RECORD +#define POLARSSL_ERR_SSL_MALLOC_FAILED MBEDTLS_ERR_SSL_ALLOC_FAILED +#define POLARSSL_ERR_SSL_NO_CIPHER_CHOSEN MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN +#define POLARSSL_ERR_SSL_NO_CLIENT_CERTIFICATE MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE +#define POLARSSL_ERR_SSL_NO_RNG MBEDTLS_ERR_SSL_NO_RNG +#define POLARSSL_ERR_SSL_NO_USABLE_CIPHERSUITE MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE +#define POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY +#define POLARSSL_ERR_SSL_PEER_VERIFY_FAILED MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED +#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH +#define POLARSSL_ERR_SSL_PRIVATE_KEY_REQUIRED MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED +#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED +#define POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE +#define POLARSSL_ERR_SSL_UNKNOWN_CIPHER MBEDTLS_ERR_SSL_UNKNOWN_CIPHER +#define POLARSSL_ERR_SSL_UNKNOWN_IDENTITY MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY +#define POLARSSL_ERR_SSL_WAITING_SERVER_HELLO_RENEGO MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO +#define POLARSSL_ERR_THREADING_BAD_INPUT_DATA MBEDTLS_ERR_THREADING_BAD_INPUT_DATA +#define POLARSSL_ERR_THREADING_FEATURE_UNAVAILABLE MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_THREADING_MUTEX_ERROR MBEDTLS_ERR_THREADING_MUTEX_ERROR +#define POLARSSL_ERR_X509_BAD_INPUT_DATA MBEDTLS_ERR_X509_BAD_INPUT_DATA +#define POLARSSL_ERR_X509_CERT_UNKNOWN_FORMAT MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT +#define POLARSSL_ERR_X509_CERT_VERIFY_FAILED MBEDTLS_ERR_X509_CERT_VERIFY_FAILED +#define POLARSSL_ERR_X509_FEATURE_UNAVAILABLE MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE +#define POLARSSL_ERR_X509_FILE_IO_ERROR MBEDTLS_ERR_X509_FILE_IO_ERROR +#define POLARSSL_ERR_X509_INVALID_ALG MBEDTLS_ERR_X509_INVALID_ALG +#define POLARSSL_ERR_X509_INVALID_DATE MBEDTLS_ERR_X509_INVALID_DATE +#define POLARSSL_ERR_X509_INVALID_EXTENSIONS MBEDTLS_ERR_X509_INVALID_EXTENSIONS +#define POLARSSL_ERR_X509_INVALID_FORMAT MBEDTLS_ERR_X509_INVALID_FORMAT +#define POLARSSL_ERR_X509_INVALID_NAME MBEDTLS_ERR_X509_INVALID_NAME +#define POLARSSL_ERR_X509_INVALID_SERIAL MBEDTLS_ERR_X509_INVALID_SERIAL +#define POLARSSL_ERR_X509_INVALID_SIGNATURE MBEDTLS_ERR_X509_INVALID_SIGNATURE +#define POLARSSL_ERR_X509_INVALID_VERSION MBEDTLS_ERR_X509_INVALID_VERSION +#define POLARSSL_ERR_X509_MALLOC_FAILED MBEDTLS_ERR_X509_ALLOC_FAILED +#define POLARSSL_ERR_X509_SIG_MISMATCH MBEDTLS_ERR_X509_SIG_MISMATCH +#define POLARSSL_ERR_X509_UNKNOWN_OID MBEDTLS_ERR_X509_UNKNOWN_OID +#define POLARSSL_ERR_X509_UNKNOWN_SIG_ALG MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG +#define POLARSSL_ERR_X509_UNKNOWN_VERSION MBEDTLS_ERR_X509_UNKNOWN_VERSION +#define POLARSSL_ERR_XTEA_INVALID_INPUT_LENGTH MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH +#define POLARSSL_GCM_H MBEDTLS_GCM_H +#define POLARSSL_HAVEGE_H MBEDTLS_HAVEGE_H +#define POLARSSL_HAVE_INT32 MBEDTLS_HAVE_INT32 +#define POLARSSL_HAVE_INT64 MBEDTLS_HAVE_INT64 +#define POLARSSL_HAVE_UDBL MBEDTLS_HAVE_UDBL +#define POLARSSL_HAVE_X86 MBEDTLS_HAVE_X86 +#define POLARSSL_HAVE_X86_64 MBEDTLS_HAVE_X86_64 +#define POLARSSL_HMAC_DRBG_H MBEDTLS_HMAC_DRBG_H +#define POLARSSL_HMAC_DRBG_PR_OFF MBEDTLS_HMAC_DRBG_PR_OFF +#define POLARSSL_HMAC_DRBG_PR_ON MBEDTLS_HMAC_DRBG_PR_ON +#define POLARSSL_KEY_EXCHANGE_DHE_PSK MBEDTLS_KEY_EXCHANGE_DHE_PSK +#define POLARSSL_KEY_EXCHANGE_DHE_RSA MBEDTLS_KEY_EXCHANGE_DHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK MBEDTLS_KEY_EXCHANGE_ECDHE_PSK +#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA MBEDTLS_KEY_EXCHANGE_ECDHE_RSA +#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA +#define POLARSSL_KEY_EXCHANGE_ECDH_RSA MBEDTLS_KEY_EXCHANGE_ECDH_RSA +#define POLARSSL_KEY_EXCHANGE_NONE MBEDTLS_KEY_EXCHANGE_NONE +#define POLARSSL_KEY_EXCHANGE_PSK MBEDTLS_KEY_EXCHANGE_PSK +#define POLARSSL_KEY_EXCHANGE_RSA MBEDTLS_KEY_EXCHANGE_RSA +#define POLARSSL_KEY_EXCHANGE_RSA_PSK MBEDTLS_KEY_EXCHANGE_RSA_PSK +#define POLARSSL_KEY_EXCHANGE__SOME__ECDHE_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__ECDHE_ENABLED +#define POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED +#define POLARSSL_KEY_EXCHANGE__WITH_CERT__ENABLED MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED +#define POLARSSL_KEY_LENGTH_DES MBEDTLS_KEY_LENGTH_DES +#define POLARSSL_KEY_LENGTH_DES_EDE MBEDTLS_KEY_LENGTH_DES_EDE +#define POLARSSL_KEY_LENGTH_DES_EDE3 MBEDTLS_KEY_LENGTH_DES_EDE3 +#define POLARSSL_KEY_LENGTH_NONE MBEDTLS_KEY_LENGTH_NONE +#define POLARSSL_MAX_BLOCK_LENGTH MBEDTLS_MAX_BLOCK_LENGTH +#define POLARSSL_MAX_IV_LENGTH MBEDTLS_MAX_IV_LENGTH +#define POLARSSL_MD2_H MBEDTLS_MD2_H +#define POLARSSL_MD4_H MBEDTLS_MD4_H +#define POLARSSL_MD5_H MBEDTLS_MD5_H +#define POLARSSL_MD_H MBEDTLS_MD_H +#define POLARSSL_MD_MAX_SIZE MBEDTLS_MD_MAX_SIZE +#define POLARSSL_MD_MD2 MBEDTLS_MD_MD2 +#define POLARSSL_MD_MD4 MBEDTLS_MD_MD4 +#define POLARSSL_MD_MD5 MBEDTLS_MD_MD5 +#define POLARSSL_MD_NONE MBEDTLS_MD_NONE +#define POLARSSL_MD_RIPEMD160 MBEDTLS_MD_RIPEMD160 +#define POLARSSL_MD_SHA1 MBEDTLS_MD_SHA1 +#define POLARSSL_MD_SHA224 MBEDTLS_MD_SHA224 +#define POLARSSL_MD_SHA256 MBEDTLS_MD_SHA256 +#define POLARSSL_MD_SHA384 MBEDTLS_MD_SHA384 +#define POLARSSL_MD_SHA512 MBEDTLS_MD_SHA512 +#define POLARSSL_MD_WRAP_H MBEDTLS_MD_WRAP_H +#define POLARSSL_MEMORY_BUFFER_ALLOC_H MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define POLARSSL_MODE_CBC MBEDTLS_MODE_CBC +#define POLARSSL_MODE_CCM MBEDTLS_MODE_CCM +#define POLARSSL_MODE_CFB MBEDTLS_MODE_CFB +#define POLARSSL_MODE_CTR MBEDTLS_MODE_CTR +#define POLARSSL_MODE_ECB MBEDTLS_MODE_ECB +#define POLARSSL_MODE_GCM MBEDTLS_MODE_GCM +#define POLARSSL_MODE_NONE MBEDTLS_MODE_NONE +#define POLARSSL_MODE_OFB MBEDTLS_MODE_OFB +#define POLARSSL_MODE_STREAM MBEDTLS_MODE_STREAM +#define POLARSSL_MPI_MAX_BITS MBEDTLS_MPI_MAX_BITS +#define POLARSSL_MPI_MAX_BITS_SCALE100 MBEDTLS_MPI_MAX_BITS_SCALE100 +#define POLARSSL_MPI_MAX_LIMBS MBEDTLS_MPI_MAX_LIMBS +#define POLARSSL_MPI_RW_BUFFER_SIZE MBEDTLS_MPI_RW_BUFFER_SIZE +#define POLARSSL_NET_H MBEDTLS_NET_SOCKETS_H +#define POLARSSL_NET_LISTEN_BACKLOG MBEDTLS_NET_LISTEN_BACKLOG +#define POLARSSL_OID_H MBEDTLS_OID_H +#define POLARSSL_OPERATION_NONE MBEDTLS_OPERATION_NONE +#define POLARSSL_PADDING_NONE MBEDTLS_PADDING_NONE +#define POLARSSL_PADDING_ONE_AND_ZEROS MBEDTLS_PADDING_ONE_AND_ZEROS +#define POLARSSL_PADDING_PKCS7 MBEDTLS_PADDING_PKCS7 +#define POLARSSL_PADDING_ZEROS MBEDTLS_PADDING_ZEROS +#define POLARSSL_PADDING_ZEROS_AND_LEN MBEDTLS_PADDING_ZEROS_AND_LEN +#define POLARSSL_PADLOCK_H MBEDTLS_PADLOCK_H +#define POLARSSL_PEM_H MBEDTLS_PEM_H +#define POLARSSL_PKCS11_H MBEDTLS_PKCS11_H +#define POLARSSL_PKCS12_H MBEDTLS_PKCS12_H +#define POLARSSL_PKCS5_H MBEDTLS_PKCS5_H +#define POLARSSL_PK_DEBUG_ECP MBEDTLS_PK_DEBUG_ECP +#define POLARSSL_PK_DEBUG_MAX_ITEMS MBEDTLS_PK_DEBUG_MAX_ITEMS +#define POLARSSL_PK_DEBUG_MPI MBEDTLS_PK_DEBUG_MPI +#define POLARSSL_PK_DEBUG_NONE MBEDTLS_PK_DEBUG_NONE +#define POLARSSL_PK_ECDSA MBEDTLS_PK_ECDSA +#define POLARSSL_PK_ECKEY MBEDTLS_PK_ECKEY +#define POLARSSL_PK_ECKEY_DH MBEDTLS_PK_ECKEY_DH +#define POLARSSL_PK_H MBEDTLS_PK_H +#define POLARSSL_PK_NONE MBEDTLS_PK_NONE +#define POLARSSL_PK_RSA MBEDTLS_PK_RSA +#define POLARSSL_PK_RSASSA_PSS MBEDTLS_PK_RSASSA_PSS +#define POLARSSL_PK_RSA_ALT MBEDTLS_PK_RSA_ALT +#define POLARSSL_PK_WRAP_H MBEDTLS_PK_WRAP_H +#define POLARSSL_PLATFORM_H MBEDTLS_PLATFORM_H +#define POLARSSL_PREMASTER_SIZE MBEDTLS_PREMASTER_SIZE +#define POLARSSL_RIPEMD160_H MBEDTLS_RIPEMD160_H +#define POLARSSL_RSA_H MBEDTLS_RSA_H +#define POLARSSL_SHA1_H MBEDTLS_SHA1_H +#define POLARSSL_SHA256_H MBEDTLS_SHA256_H +#define POLARSSL_SHA512_H MBEDTLS_SHA512_H +#define POLARSSL_SSL_CACHE_H MBEDTLS_SSL_CACHE_H +#define POLARSSL_SSL_CIPHERSUITES_H MBEDTLS_SSL_CIPHERSUITES_H +#define POLARSSL_SSL_COOKIE_H MBEDTLS_SSL_COOKIE_H +#define POLARSSL_SSL_H MBEDTLS_SSL_H +#define POLARSSL_THREADING_H MBEDTLS_THREADING_H +#define POLARSSL_THREADING_IMPL MBEDTLS_THREADING_IMPL +#define POLARSSL_TIMING_H MBEDTLS_TIMING_H +#define POLARSSL_VERSION_H MBEDTLS_VERSION_H +#define POLARSSL_VERSION_MAJOR MBEDTLS_VERSION_MAJOR +#define POLARSSL_VERSION_MINOR MBEDTLS_VERSION_MINOR +#define POLARSSL_VERSION_NUMBER MBEDTLS_VERSION_NUMBER +#define POLARSSL_VERSION_PATCH MBEDTLS_VERSION_PATCH +#define POLARSSL_VERSION_STRING MBEDTLS_VERSION_STRING +#define POLARSSL_VERSION_STRING_FULL MBEDTLS_VERSION_STRING_FULL +#define POLARSSL_X509_CRL_H MBEDTLS_X509_CRL_H +#define POLARSSL_X509_CRT_H MBEDTLS_X509_CRT_H +#define POLARSSL_X509_CSR_H MBEDTLS_X509_CSR_H +#define POLARSSL_X509_H MBEDTLS_X509_H +#define POLARSSL_XTEA_H MBEDTLS_XTEA_H +#define RSA_CRYPT MBEDTLS_RSA_CRYPT +#define RSA_PKCS_V15 MBEDTLS_RSA_PKCS_V15 +#define RSA_PKCS_V21 MBEDTLS_RSA_PKCS_V21 +#define RSA_PRIVATE MBEDTLS_RSA_PRIVATE +#define RSA_PUBLIC MBEDTLS_RSA_PUBLIC +#define RSA_SALT_LEN_ANY MBEDTLS_RSA_SALT_LEN_ANY +#define RSA_SIGN MBEDTLS_RSA_SIGN +#define SSL_ALERT_LEVEL_FATAL MBEDTLS_SSL_ALERT_LEVEL_FATAL +#define SSL_ALERT_LEVEL_WARNING MBEDTLS_SSL_ALERT_LEVEL_WARNING +#define SSL_ALERT_MSG_ACCESS_DENIED MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED +#define SSL_ALERT_MSG_BAD_CERT MBEDTLS_SSL_ALERT_MSG_BAD_CERT +#define SSL_ALERT_MSG_BAD_RECORD_MAC MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC +#define SSL_ALERT_MSG_CERT_EXPIRED MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED +#define SSL_ALERT_MSG_CERT_REVOKED MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED +#define SSL_ALERT_MSG_CERT_UNKNOWN MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN +#define SSL_ALERT_MSG_CLOSE_NOTIFY MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY +#define SSL_ALERT_MSG_DECODE_ERROR MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR +#define SSL_ALERT_MSG_DECOMPRESSION_FAILURE MBEDTLS_SSL_ALERT_MSG_DECOMPRESSION_FAILURE +#define SSL_ALERT_MSG_DECRYPTION_FAILED MBEDTLS_SSL_ALERT_MSG_DECRYPTION_FAILED +#define SSL_ALERT_MSG_DECRYPT_ERROR MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR +#define SSL_ALERT_MSG_EXPORT_RESTRICTION MBEDTLS_SSL_ALERT_MSG_EXPORT_RESTRICTION +#define SSL_ALERT_MSG_HANDSHAKE_FAILURE MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE +#define SSL_ALERT_MSG_ILLEGAL_PARAMETER MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER +#define SSL_ALERT_MSG_INAPROPRIATE_FALLBACK MBEDTLS_SSL_ALERT_MSG_INAPROPRIATE_FALLBACK +#define SSL_ALERT_MSG_INSUFFICIENT_SECURITY MBEDTLS_SSL_ALERT_MSG_INSUFFICIENT_SECURITY +#define SSL_ALERT_MSG_INTERNAL_ERROR MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR +#define SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL MBEDTLS_SSL_ALERT_MSG_NO_APPLICATION_PROTOCOL +#define SSL_ALERT_MSG_NO_CERT MBEDTLS_SSL_ALERT_MSG_NO_CERT +#define SSL_ALERT_MSG_NO_RENEGOTIATION MBEDTLS_SSL_ALERT_MSG_NO_RENEGOTIATION +#define SSL_ALERT_MSG_PROTOCOL_VERSION MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION +#define SSL_ALERT_MSG_RECORD_OVERFLOW MBEDTLS_SSL_ALERT_MSG_RECORD_OVERFLOW +#define SSL_ALERT_MSG_UNEXPECTED_MESSAGE MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE +#define SSL_ALERT_MSG_UNKNOWN_CA MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA +#define SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY MBEDTLS_SSL_ALERT_MSG_UNKNOWN_PSK_IDENTITY +#define SSL_ALERT_MSG_UNRECOGNIZED_NAME MBEDTLS_SSL_ALERT_MSG_UNRECOGNIZED_NAME +#define SSL_ALERT_MSG_UNSUPPORTED_CERT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT +#define SSL_ALERT_MSG_UNSUPPORTED_EXT MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT +#define SSL_ALERT_MSG_USER_CANCELED MBEDTLS_SSL_ALERT_MSG_USER_CANCELED +#define SSL_ANTI_REPLAY_DISABLED MBEDTLS_SSL_ANTI_REPLAY_DISABLED +#define SSL_ANTI_REPLAY_ENABLED MBEDTLS_SSL_ANTI_REPLAY_ENABLED +#define SSL_ARC4_DISABLED MBEDTLS_SSL_ARC4_DISABLED +#define SSL_ARC4_ENABLED MBEDTLS_SSL_ARC4_ENABLED +#define SSL_BUFFER_LEN MBEDTLS_SSL_BUFFER_LEN +#define SSL_CACHE_DEFAULT_MAX_ENTRIES MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES +#define SSL_CACHE_DEFAULT_TIMEOUT MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT +#define SSL_CBC_RECORD_SPLITTING_DISABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED +#define SSL_CBC_RECORD_SPLITTING_ENABLED MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED +#define SSL_CERTIFICATE_REQUEST MBEDTLS_SSL_CERTIFICATE_REQUEST +#define SSL_CERTIFICATE_VERIFY MBEDTLS_SSL_CERTIFICATE_VERIFY +#define SSL_CERT_TYPE_ECDSA_SIGN MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN +#define SSL_CERT_TYPE_RSA_SIGN MBEDTLS_SSL_CERT_TYPE_RSA_SIGN +#define SSL_CHANNEL_INBOUND MBEDTLS_SSL_CHANNEL_INBOUND +#define SSL_CHANNEL_OUTBOUND MBEDTLS_SSL_CHANNEL_OUTBOUND +#define SSL_CIPHERSUITES MBEDTLS_SSL_CIPHERSUITES +#define SSL_CLIENT_CERTIFICATE MBEDTLS_SSL_CLIENT_CERTIFICATE +#define SSL_CLIENT_CHANGE_CIPHER_SPEC MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC +#define SSL_CLIENT_FINISHED MBEDTLS_SSL_CLIENT_FINISHED +#define SSL_CLIENT_HELLO MBEDTLS_SSL_CLIENT_HELLO +#define SSL_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_CLIENT_KEY_EXCHANGE +#define SSL_COMPRESSION_ADD MBEDTLS_SSL_COMPRESSION_ADD +#define SSL_COMPRESS_DEFLATE MBEDTLS_SSL_COMPRESS_DEFLATE +#define SSL_COMPRESS_NULL MBEDTLS_SSL_COMPRESS_NULL +#define SSL_DEBUG_BUF MBEDTLS_SSL_DEBUG_BUF +#define SSL_DEBUG_CRT MBEDTLS_SSL_DEBUG_CRT +#define SSL_DEBUG_ECP MBEDTLS_SSL_DEBUG_ECP +#define SSL_DEBUG_MPI MBEDTLS_SSL_DEBUG_MPI +#define SSL_DEBUG_MSG MBEDTLS_SSL_DEBUG_MSG +#define SSL_DEBUG_RET MBEDTLS_SSL_DEBUG_RET +#define SSL_DEFAULT_TICKET_LIFETIME MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME +#define SSL_DTLS_TIMEOUT_DFL_MAX MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX +#define SSL_DTLS_TIMEOUT_DFL_MIN MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN +#define SSL_EMPTY_RENEGOTIATION_INFO MBEDTLS_SSL_EMPTY_RENEGOTIATION_INFO +#define SSL_ETM_DISABLED MBEDTLS_SSL_ETM_DISABLED +#define SSL_ETM_ENABLED MBEDTLS_SSL_ETM_ENABLED +#define SSL_EXTENDED_MS_DISABLED MBEDTLS_SSL_EXTENDED_MS_DISABLED +#define SSL_EXTENDED_MS_ENABLED MBEDTLS_SSL_EXTENDED_MS_ENABLED +#define SSL_FALLBACK_SCSV MBEDTLS_SSL_FALLBACK_SCSV +#define SSL_FLUSH_BUFFERS MBEDTLS_SSL_FLUSH_BUFFERS +#define SSL_HANDSHAKE_OVER MBEDTLS_SSL_HANDSHAKE_OVER +#define SSL_HANDSHAKE_WRAPUP MBEDTLS_SSL_HANDSHAKE_WRAPUP +#define SSL_HASH_MD5 MBEDTLS_SSL_HASH_MD5 +#define SSL_HASH_NONE MBEDTLS_SSL_HASH_NONE +#define SSL_HASH_SHA1 MBEDTLS_SSL_HASH_SHA1 +#define SSL_HASH_SHA224 MBEDTLS_SSL_HASH_SHA224 +#define SSL_HASH_SHA256 MBEDTLS_SSL_HASH_SHA256 +#define SSL_HASH_SHA384 MBEDTLS_SSL_HASH_SHA384 +#define SSL_HASH_SHA512 MBEDTLS_SSL_HASH_SHA512 +#define SSL_HELLO_REQUEST MBEDTLS_SSL_HELLO_REQUEST +#define SSL_HS_CERTIFICATE MBEDTLS_SSL_HS_CERTIFICATE +#define SSL_HS_CERTIFICATE_REQUEST MBEDTLS_SSL_HS_CERTIFICATE_REQUEST +#define SSL_HS_CERTIFICATE_VERIFY MBEDTLS_SSL_HS_CERTIFICATE_VERIFY +#define SSL_HS_CLIENT_HELLO MBEDTLS_SSL_HS_CLIENT_HELLO +#define SSL_HS_CLIENT_KEY_EXCHANGE MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE +#define SSL_HS_FINISHED MBEDTLS_SSL_HS_FINISHED +#define SSL_HS_HELLO_REQUEST MBEDTLS_SSL_HS_HELLO_REQUEST +#define SSL_HS_HELLO_VERIFY_REQUEST MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST +#define SSL_HS_NEW_SESSION_TICKET MBEDTLS_SSL_HS_NEW_SESSION_TICKET +#define SSL_HS_SERVER_HELLO MBEDTLS_SSL_HS_SERVER_HELLO +#define SSL_HS_SERVER_HELLO_DONE MBEDTLS_SSL_HS_SERVER_HELLO_DONE +#define SSL_HS_SERVER_KEY_EXCHANGE MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE +#define SSL_INITIAL_HANDSHAKE MBEDTLS_SSL_INITIAL_HANDSHAKE +#define SSL_IS_CLIENT MBEDTLS_SSL_IS_CLIENT +#define SSL_IS_FALLBACK MBEDTLS_SSL_IS_FALLBACK +#define SSL_IS_NOT_FALLBACK MBEDTLS_SSL_IS_NOT_FALLBACK +#define SSL_IS_SERVER MBEDTLS_SSL_IS_SERVER +#define SSL_LEGACY_ALLOW_RENEGOTIATION MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION +#define SSL_LEGACY_BREAK_HANDSHAKE MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE +#define SSL_LEGACY_NO_RENEGOTIATION MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION +#define SSL_LEGACY_RENEGOTIATION MBEDTLS_SSL_LEGACY_RENEGOTIATION +#define SSL_MAC_ADD MBEDTLS_SSL_MAC_ADD +#define SSL_MAJOR_VERSION_3 MBEDTLS_SSL_MAJOR_VERSION_3 +#define SSL_MAX_CONTENT_LEN MBEDTLS_SSL_MAX_CONTENT_LEN +#define SSL_MAX_FRAG_LEN_1024 MBEDTLS_SSL_MAX_FRAG_LEN_1024 +#define SSL_MAX_FRAG_LEN_2048 MBEDTLS_SSL_MAX_FRAG_LEN_2048 +#define SSL_MAX_FRAG_LEN_4096 MBEDTLS_SSL_MAX_FRAG_LEN_4096 +#define SSL_MAX_FRAG_LEN_512 MBEDTLS_SSL_MAX_FRAG_LEN_512 +#define SSL_MAX_FRAG_LEN_INVALID MBEDTLS_SSL_MAX_FRAG_LEN_INVALID +#define SSL_MAX_FRAG_LEN_NONE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define SSL_MAX_MAJOR_VERSION MBEDTLS_SSL_MAX_MAJOR_VERSION +#define SSL_MAX_MINOR_VERSION MBEDTLS_SSL_MAX_MINOR_VERSION +#define SSL_MINOR_VERSION_0 MBEDTLS_SSL_MINOR_VERSION_0 +#define SSL_MINOR_VERSION_1 MBEDTLS_SSL_MINOR_VERSION_1 +#define SSL_MINOR_VERSION_2 MBEDTLS_SSL_MINOR_VERSION_2 +#define SSL_MINOR_VERSION_3 MBEDTLS_SSL_MINOR_VERSION_3 +#define SSL_MIN_MAJOR_VERSION MBEDTLS_SSL_MIN_MAJOR_VERSION +#define SSL_MIN_MINOR_VERSION MBEDTLS_SSL_MIN_MINOR_VERSION +#define SSL_MSG_ALERT MBEDTLS_SSL_MSG_ALERT +#define SSL_MSG_APPLICATION_DATA MBEDTLS_SSL_MSG_APPLICATION_DATA +#define SSL_MSG_CHANGE_CIPHER_SPEC MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC +#define SSL_MSG_HANDSHAKE MBEDTLS_SSL_MSG_HANDSHAKE +#define SSL_PADDING_ADD MBEDTLS_SSL_PADDING_ADD +#define SSL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION +#define SSL_RENEGOTIATION_DISABLED MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define SSL_RENEGOTIATION_DONE MBEDTLS_SSL_RENEGOTIATION_DONE +#define SSL_RENEGOTIATION_ENABLED MBEDTLS_SSL_RENEGOTIATION_ENABLED +#define SSL_RENEGOTIATION_NOT_ENFORCED MBEDTLS_SSL_RENEGOTIATION_NOT_ENFORCED +#define SSL_RENEGOTIATION_PENDING MBEDTLS_SSL_RENEGOTIATION_PENDING +#define SSL_RENEGO_MAX_RECORDS_DEFAULT MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT +#define SSL_RETRANS_FINISHED MBEDTLS_SSL_RETRANS_FINISHED +#define SSL_RETRANS_PREPARING MBEDTLS_SSL_RETRANS_PREPARING +#define SSL_RETRANS_SENDING MBEDTLS_SSL_RETRANS_SENDING +#define SSL_RETRANS_WAITING MBEDTLS_SSL_RETRANS_WAITING +#define SSL_SECURE_RENEGOTIATION MBEDTLS_SSL_SECURE_RENEGOTIATION +#define SSL_SERVER_CERTIFICATE MBEDTLS_SSL_SERVER_CERTIFICATE +#define SSL_SERVER_CHANGE_CIPHER_SPEC MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC +#define SSL_SERVER_FINISHED MBEDTLS_SSL_SERVER_FINISHED +#define SSL_SERVER_HELLO MBEDTLS_SSL_SERVER_HELLO +#define SSL_SERVER_HELLO_DONE MBEDTLS_SSL_SERVER_HELLO_DONE +#define SSL_SERVER_HELLO_VERIFY_REQUEST_SENT MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT +#define SSL_SERVER_KEY_EXCHANGE MBEDTLS_SSL_SERVER_KEY_EXCHANGE +#define SSL_SERVER_NEW_SESSION_TICKET MBEDTLS_SSL_SERVER_NEW_SESSION_TICKET +#define SSL_SESSION_TICKETS_DISABLED MBEDTLS_SSL_SESSION_TICKETS_DISABLED +#define SSL_SESSION_TICKETS_ENABLED MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define SSL_SIG_ANON MBEDTLS_SSL_SIG_ANON +#define SSL_SIG_ECDSA MBEDTLS_SSL_SIG_ECDSA +#define SSL_SIG_RSA MBEDTLS_SSL_SIG_RSA +#define SSL_TRANSPORT_DATAGRAM MBEDTLS_SSL_TRANSPORT_DATAGRAM +#define SSL_TRANSPORT_STREAM MBEDTLS_SSL_TRANSPORT_STREAM +#define SSL_TRUNCATED_HMAC_LEN MBEDTLS_SSL_TRUNCATED_HMAC_LEN +#define SSL_TRUNC_HMAC_DISABLED MBEDTLS_SSL_TRUNC_HMAC_DISABLED +#define SSL_TRUNC_HMAC_ENABLED MBEDTLS_SSL_TRUNC_HMAC_ENABLED +#define SSL_VERIFY_DATA_MAX_LEN MBEDTLS_SSL_VERIFY_DATA_MAX_LEN +#define SSL_VERIFY_NONE MBEDTLS_SSL_VERIFY_NONE +#define SSL_VERIFY_OPTIONAL MBEDTLS_SSL_VERIFY_OPTIONAL +#define SSL_VERIFY_REQUIRED MBEDTLS_SSL_VERIFY_REQUIRED +#define TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_AES_128_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM +#define TLS_DHE_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8 +#define TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_AES_256_CCM MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM +#define TLS_DHE_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8 +#define TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA +#define TLS_DHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 +#define TLS_DHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 +#define TLS_DHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_128_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM +#define TLS_DHE_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 +#define TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_AES_256_CCM MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM +#define TLS_DHE_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 +#define TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_DHE_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM +#define TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 +#define TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA +#define TLS_ECDHE_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_PSK_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA +#define TLS_ECDHE_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 +#define TLS_ECDHE_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 +#define TLS_ECDHE_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA +#define TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDHE_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA +#define TLS_ECDHE_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA +#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_ECDSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA +#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA +#define TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA +#define TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_ECDH_RSA_WITH_NULL_SHA MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA +#define TLS_ECDH_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA +#define TLS_EXT_ALPN MBEDTLS_TLS_EXT_ALPN +#define TLS_EXT_ENCRYPT_THEN_MAC MBEDTLS_TLS_EXT_ENCRYPT_THEN_MAC +#define TLS_EXT_EXTENDED_MASTER_SECRET MBEDTLS_TLS_EXT_EXTENDED_MASTER_SECRET +#define TLS_EXT_MAX_FRAGMENT_LENGTH MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH +#define TLS_EXT_RENEGOTIATION_INFO MBEDTLS_TLS_EXT_RENEGOTIATION_INFO +#define TLS_EXT_SERVERNAME MBEDTLS_TLS_EXT_SERVERNAME +#define TLS_EXT_SERVERNAME_HOSTNAME MBEDTLS_TLS_EXT_SERVERNAME_HOSTNAME +#define TLS_EXT_SESSION_TICKET MBEDTLS_TLS_EXT_SESSION_TICKET +#define TLS_EXT_SIG_ALG MBEDTLS_TLS_EXT_SIG_ALG +#define TLS_EXT_SUPPORTED_ELLIPTIC_CURVES MBEDTLS_TLS_EXT_SUPPORTED_ELLIPTIC_CURVES +#define TLS_EXT_SUPPORTED_POINT_FORMATS MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS +#define TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS_PRESENT +#define TLS_EXT_TRUNCATED_HMAC MBEDTLS_TLS_EXT_TRUNCATED_HMAC +#define TLS_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA +#define TLS_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_PSK_WITH_AES_128_CCM MBEDTLS_TLS_PSK_WITH_AES_128_CCM +#define TLS_PSK_WITH_AES_128_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8 +#define TLS_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA +#define TLS_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_PSK_WITH_AES_256_CCM MBEDTLS_TLS_PSK_WITH_AES_256_CCM +#define TLS_PSK_WITH_AES_256_CCM_8 MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8 +#define TLS_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_PSK_WITH_NULL_SHA MBEDTLS_TLS_PSK_WITH_NULL_SHA +#define TLS_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_PSK_WITH_NULL_SHA256 +#define TLS_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_PSK_WITH_NULL_SHA384 +#define TLS_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_PSK_WITH_RC4_128_SHA +#define TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA +#define TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 +#define TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_PSK_WITH_NULL_SHA MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA +#define TLS_RSA_PSK_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 +#define TLS_RSA_PSK_WITH_NULL_SHA384 MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 +#define TLS_RSA_PSK_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA +#define TLS_RSA_WITH_AES_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 +#define TLS_RSA_WITH_AES_128_CCM MBEDTLS_TLS_RSA_WITH_AES_128_CCM +#define TLS_RSA_WITH_AES_128_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8 +#define TLS_RSA_WITH_AES_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 +#define TLS_RSA_WITH_AES_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA +#define TLS_RSA_WITH_AES_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 +#define TLS_RSA_WITH_AES_256_CCM MBEDTLS_TLS_RSA_WITH_AES_256_CCM +#define TLS_RSA_WITH_AES_256_CCM_8 MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8 +#define TLS_RSA_WITH_AES_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA +#define TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 +#define TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 +#define TLS_RSA_WITH_DES_CBC_SHA MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA +#define TLS_RSA_WITH_NULL_MD5 MBEDTLS_TLS_RSA_WITH_NULL_MD5 +#define TLS_RSA_WITH_NULL_SHA MBEDTLS_TLS_RSA_WITH_NULL_SHA +#define TLS_RSA_WITH_NULL_SHA256 MBEDTLS_TLS_RSA_WITH_NULL_SHA256 +#define TLS_RSA_WITH_RC4_128_MD5 MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 +#define TLS_RSA_WITH_RC4_128_SHA MBEDTLS_TLS_RSA_WITH_RC4_128_SHA +#define X509_CRT_VERSION_1 MBEDTLS_X509_CRT_VERSION_1 +#define X509_CRT_VERSION_2 MBEDTLS_X509_CRT_VERSION_2 +#define X509_CRT_VERSION_3 MBEDTLS_X509_CRT_VERSION_3 +#define X509_FORMAT_DER MBEDTLS_X509_FORMAT_DER +#define X509_FORMAT_PEM MBEDTLS_X509_FORMAT_PEM +#define X509_MAX_DN_NAME_SIZE MBEDTLS_X509_MAX_DN_NAME_SIZE +#define X509_RFC5280_MAX_SERIAL_LEN MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN +#define X509_RFC5280_UTC_TIME_LEN MBEDTLS_X509_RFC5280_UTC_TIME_LEN +#define XTEA_DECRYPT MBEDTLS_XTEA_DECRYPT +#define XTEA_ENCRYPT MBEDTLS_XTEA_ENCRYPT +#define _asn1_bitstring mbedtls_asn1_bitstring +#define _asn1_buf mbedtls_asn1_buf +#define _asn1_named_data mbedtls_asn1_named_data +#define _asn1_sequence mbedtls_asn1_sequence +#define _ssl_cache_context mbedtls_ssl_cache_context +#define _ssl_cache_entry mbedtls_ssl_cache_entry +#define _ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define _ssl_context mbedtls_ssl_context +#define _ssl_flight_item mbedtls_ssl_flight_item +#define _ssl_handshake_params mbedtls_ssl_handshake_params +#define _ssl_key_cert mbedtls_ssl_key_cert +#define _ssl_premaster_secret mbedtls_ssl_premaster_secret +#define _ssl_session mbedtls_ssl_session +#define _ssl_transform mbedtls_ssl_transform +#define _x509_crl mbedtls_x509_crl +#define _x509_crl_entry mbedtls_x509_crl_entry +#define _x509_crt mbedtls_x509_crt +#define _x509_csr mbedtls_x509_csr +#define _x509_time mbedtls_x509_time +#define _x509write_cert mbedtls_x509write_cert +#define _x509write_csr mbedtls_x509write_csr +#define aes_context mbedtls_aes_context +#define aes_crypt_cbc mbedtls_aes_crypt_cbc +#define aes_crypt_cfb128 mbedtls_aes_crypt_cfb128 +#define aes_crypt_cfb8 mbedtls_aes_crypt_cfb8 +#define aes_crypt_ctr mbedtls_aes_crypt_ctr +#define aes_crypt_ecb mbedtls_aes_crypt_ecb +#define aes_free mbedtls_aes_free +#define aes_init mbedtls_aes_init +#define aes_self_test mbedtls_aes_self_test +#define aes_setkey_dec mbedtls_aes_setkey_dec +#define aes_setkey_enc mbedtls_aes_setkey_enc +#define aesni_crypt_ecb mbedtls_aesni_crypt_ecb +#define aesni_gcm_mult mbedtls_aesni_gcm_mult +#define aesni_inverse_key mbedtls_aesni_inverse_key +#define aesni_setkey_enc mbedtls_aesni_setkey_enc +#define aesni_supports mbedtls_aesni_has_support +#define alarmed mbedtls_timing_alarmed +#define arc4_context mbedtls_arc4_context +#define arc4_crypt mbedtls_arc4_crypt +#define arc4_free mbedtls_arc4_free +#define arc4_init mbedtls_arc4_init +#define arc4_self_test mbedtls_arc4_self_test +#define arc4_setup mbedtls_arc4_setup +#define asn1_bitstring mbedtls_asn1_bitstring +#define asn1_buf mbedtls_asn1_buf +#define asn1_find_named_data mbedtls_asn1_find_named_data +#define asn1_free_named_data mbedtls_asn1_free_named_data +#define asn1_free_named_data_list mbedtls_asn1_free_named_data_list +#define asn1_get_alg mbedtls_asn1_get_alg +#define asn1_get_alg_null mbedtls_asn1_get_alg_null +#define asn1_get_bitstring mbedtls_asn1_get_bitstring +#define asn1_get_bitstring_null mbedtls_asn1_get_bitstring_null +#define asn1_get_bool mbedtls_asn1_get_bool +#define asn1_get_int mbedtls_asn1_get_int +#define asn1_get_len mbedtls_asn1_get_len +#define asn1_get_mpi mbedtls_asn1_get_mpi +#define asn1_get_sequence_of mbedtls_asn1_get_sequence_of +#define asn1_get_tag mbedtls_asn1_get_tag +#define asn1_named_data mbedtls_asn1_named_data +#define asn1_sequence mbedtls_asn1_sequence +#define asn1_store_named_data mbedtls_asn1_store_named_data +#define asn1_write_algorithm_identifier mbedtls_asn1_write_algorithm_identifier +#define asn1_write_bitstring mbedtls_asn1_write_bitstring +#define asn1_write_bool mbedtls_asn1_write_bool +#define asn1_write_ia5_string mbedtls_asn1_write_ia5_string +#define asn1_write_int mbedtls_asn1_write_int +#define asn1_write_len mbedtls_asn1_write_len +#define asn1_write_mpi mbedtls_asn1_write_mpi +#define asn1_write_null mbedtls_asn1_write_null +#define asn1_write_octet_string mbedtls_asn1_write_octet_string +#define asn1_write_oid mbedtls_asn1_write_oid +#define asn1_write_printable_string mbedtls_asn1_write_printable_string +#define asn1_write_raw_buffer mbedtls_asn1_write_raw_buffer +#define asn1_write_tag mbedtls_asn1_write_tag +#define base64_decode mbedtls_base64_decode +#define base64_encode mbedtls_base64_encode +#define base64_self_test mbedtls_base64_self_test +#define blowfish_context mbedtls_blowfish_context +#define blowfish_crypt_cbc mbedtls_blowfish_crypt_cbc +#define blowfish_crypt_cfb64 mbedtls_blowfish_crypt_cfb64 +#define blowfish_crypt_ctr mbedtls_blowfish_crypt_ctr +#define blowfish_crypt_ecb mbedtls_blowfish_crypt_ecb +#define blowfish_free mbedtls_blowfish_free +#define blowfish_init mbedtls_blowfish_init +#define blowfish_setkey mbedtls_blowfish_setkey +#define camellia_context mbedtls_camellia_context +#define camellia_crypt_cbc mbedtls_camellia_crypt_cbc +#define camellia_crypt_cfb128 mbedtls_camellia_crypt_cfb128 +#define camellia_crypt_ctr mbedtls_camellia_crypt_ctr +#define camellia_crypt_ecb mbedtls_camellia_crypt_ecb +#define camellia_free mbedtls_camellia_free +#define camellia_init mbedtls_camellia_init +#define camellia_self_test mbedtls_camellia_self_test +#define camellia_setkey_dec mbedtls_camellia_setkey_dec +#define camellia_setkey_enc mbedtls_camellia_setkey_enc +#define ccm_auth_decrypt mbedtls_ccm_auth_decrypt +#define ccm_context mbedtls_ccm_context +#define ccm_encrypt_and_tag mbedtls_ccm_encrypt_and_tag +#define ccm_free mbedtls_ccm_free +#define ccm_init mbedtls_ccm_init +#define ccm_self_test mbedtls_ccm_self_test +#define cipher_auth_decrypt mbedtls_cipher_auth_decrypt +#define cipher_auth_encrypt mbedtls_cipher_auth_encrypt +#define cipher_base_t mbedtls_cipher_base_t +#define cipher_check_tag mbedtls_cipher_check_tag +#define cipher_context_t mbedtls_cipher_context_t +#define cipher_crypt mbedtls_cipher_crypt +#define cipher_definition_t mbedtls_cipher_definition_t +#define cipher_definitions mbedtls_cipher_definitions +#define cipher_finish mbedtls_cipher_finish +#define cipher_free mbedtls_cipher_free +#define cipher_get_block_size mbedtls_cipher_get_block_size +#define cipher_get_cipher_mode mbedtls_cipher_get_cipher_mode +#define cipher_get_iv_size mbedtls_cipher_get_iv_size +#define cipher_get_key_size mbedtls_cipher_get_key_bitlen +#define cipher_get_name mbedtls_cipher_get_name +#define cipher_get_operation mbedtls_cipher_get_operation +#define cipher_get_type mbedtls_cipher_get_type +#define cipher_id_t mbedtls_cipher_id_t +#define cipher_info_from_string mbedtls_cipher_info_from_string +#define cipher_info_from_type mbedtls_cipher_info_from_type +#define cipher_info_from_values mbedtls_cipher_info_from_values +#define cipher_info_t mbedtls_cipher_info_t +#define cipher_init mbedtls_cipher_init +#define cipher_init_ctx mbedtls_cipher_setup +#define cipher_list mbedtls_cipher_list +#define cipher_mode_t mbedtls_cipher_mode_t +#define cipher_padding_t mbedtls_cipher_padding_t +#define cipher_reset mbedtls_cipher_reset +#define cipher_set_iv mbedtls_cipher_set_iv +#define cipher_set_padding_mode mbedtls_cipher_set_padding_mode +#define cipher_setkey mbedtls_cipher_setkey +#define cipher_type_t mbedtls_cipher_type_t +#define cipher_update mbedtls_cipher_update +#define cipher_update_ad mbedtls_cipher_update_ad +#define cipher_write_tag mbedtls_cipher_write_tag +#define ctr_drbg_context mbedtls_ctr_drbg_context +#define ctr_drbg_free mbedtls_ctr_drbg_free +#define ctr_drbg_init mbedtls_ctr_drbg_init +#define ctr_drbg_random mbedtls_ctr_drbg_random +#define ctr_drbg_random_with_add mbedtls_ctr_drbg_random_with_add +#define ctr_drbg_reseed mbedtls_ctr_drbg_reseed +#define ctr_drbg_self_test mbedtls_ctr_drbg_self_test +#define ctr_drbg_set_entropy_len mbedtls_ctr_drbg_set_entropy_len +#define ctr_drbg_set_prediction_resistance mbedtls_ctr_drbg_set_prediction_resistance +#define ctr_drbg_set_reseed_interval mbedtls_ctr_drbg_set_reseed_interval +#define ctr_drbg_update mbedtls_ctr_drbg_update +#define ctr_drbg_update_seed_file mbedtls_ctr_drbg_update_seed_file +#define ctr_drbg_write_seed_file mbedtls_ctr_drbg_write_seed_file +#define debug_print_buf mbedtls_debug_print_buf +#define debug_print_crt mbedtls_debug_print_crt +#define debug_print_ecp mbedtls_debug_print_ecp +#define debug_print_mpi mbedtls_debug_print_mpi +#define debug_print_msg mbedtls_debug_print_msg +#define debug_print_ret mbedtls_debug_print_ret +#define debug_set_threshold mbedtls_debug_set_threshold +#define des3_context mbedtls_des3_context +#define des3_crypt_cbc mbedtls_des3_crypt_cbc +#define des3_crypt_ecb mbedtls_des3_crypt_ecb +#define des3_free mbedtls_des3_free +#define des3_init mbedtls_des3_init +#define des3_set2key_dec mbedtls_des3_set2key_dec +#define des3_set2key_enc mbedtls_des3_set2key_enc +#define des3_set3key_dec mbedtls_des3_set3key_dec +#define des3_set3key_enc mbedtls_des3_set3key_enc +#define des_context mbedtls_des_context +#define des_crypt_cbc mbedtls_des_crypt_cbc +#define des_crypt_ecb mbedtls_des_crypt_ecb +#define des_free mbedtls_des_free +#define des_init mbedtls_des_init +#define des_key_check_key_parity mbedtls_des_key_check_key_parity +#define des_key_check_weak mbedtls_des_key_check_weak +#define des_key_set_parity mbedtls_des_key_set_parity +#define des_self_test mbedtls_des_self_test +#define des_setkey_dec mbedtls_des_setkey_dec +#define des_setkey_enc mbedtls_des_setkey_enc +#define dhm_calc_secret mbedtls_dhm_calc_secret +#define dhm_context mbedtls_dhm_context +#define dhm_free mbedtls_dhm_free +#define dhm_init mbedtls_dhm_init +#define dhm_make_params mbedtls_dhm_make_params +#define dhm_make_public mbedtls_dhm_make_public +#define dhm_parse_dhm mbedtls_dhm_parse_dhm +#define dhm_parse_dhmfile mbedtls_dhm_parse_dhmfile +#define dhm_read_params mbedtls_dhm_read_params +#define dhm_read_public mbedtls_dhm_read_public +#define dhm_self_test mbedtls_dhm_self_test +#define ecdh_calc_secret mbedtls_ecdh_calc_secret +#define ecdh_compute_shared mbedtls_ecdh_compute_shared +#define ecdh_context mbedtls_ecdh_context +#define ecdh_free mbedtls_ecdh_free +#define ecdh_gen_public mbedtls_ecdh_gen_public +#define ecdh_get_params mbedtls_ecdh_get_params +#define ecdh_init mbedtls_ecdh_init +#define ecdh_make_params mbedtls_ecdh_make_params +#define ecdh_make_public mbedtls_ecdh_make_public +#define ecdh_read_params mbedtls_ecdh_read_params +#define ecdh_read_public mbedtls_ecdh_read_public +#define ecdh_side mbedtls_ecdh_side +#define ecdsa_context mbedtls_ecdsa_context +#define ecdsa_free mbedtls_ecdsa_free +#define ecdsa_from_keypair mbedtls_ecdsa_from_keypair +#define ecdsa_genkey mbedtls_ecdsa_genkey +#define ecdsa_info mbedtls_ecdsa_info +#define ecdsa_init mbedtls_ecdsa_init +#define ecdsa_read_signature mbedtls_ecdsa_read_signature +#define ecdsa_sign mbedtls_ecdsa_sign +#define ecdsa_sign_det mbedtls_ecdsa_sign_det +#define ecdsa_verify mbedtls_ecdsa_verify +#define ecdsa_write_signature mbedtls_ecdsa_write_signature +#define ecdsa_write_signature_det mbedtls_ecdsa_write_signature_det +#define eckey_info mbedtls_eckey_info +#define eckeydh_info mbedtls_eckeydh_info +#define ecp_check_privkey mbedtls_ecp_check_privkey +#define ecp_check_pub_priv mbedtls_ecp_check_pub_priv +#define ecp_check_pubkey mbedtls_ecp_check_pubkey +#define ecp_copy mbedtls_ecp_copy +#define ecp_curve_info mbedtls_ecp_curve_info +#define ecp_curve_info_from_grp_id mbedtls_ecp_curve_info_from_grp_id +#define ecp_curve_info_from_name mbedtls_ecp_curve_info_from_name +#define ecp_curve_info_from_tls_id mbedtls_ecp_curve_info_from_tls_id +#define ecp_curve_list mbedtls_ecp_curve_list +#define ecp_gen_key mbedtls_ecp_gen_key +#define ecp_gen_keypair mbedtls_ecp_gen_keypair +#define ecp_group mbedtls_ecp_group +#define ecp_group_copy mbedtls_ecp_group_copy +#define ecp_group_free mbedtls_ecp_group_free +#define ecp_group_id mbedtls_ecp_group_id +#define ecp_group_init mbedtls_ecp_group_init +#define ecp_grp_id_list mbedtls_ecp_grp_id_list +#define ecp_is_zero mbedtls_ecp_is_zero +#define ecp_keypair mbedtls_ecp_keypair +#define ecp_keypair_free mbedtls_ecp_keypair_free +#define ecp_keypair_init mbedtls_ecp_keypair_init +#define ecp_mul mbedtls_ecp_mul +#define ecp_point mbedtls_ecp_point +#define ecp_point_free mbedtls_ecp_point_free +#define ecp_point_init mbedtls_ecp_point_init +#define ecp_point_read_binary mbedtls_ecp_point_read_binary +#define ecp_point_read_string mbedtls_ecp_point_read_string +#define ecp_point_write_binary mbedtls_ecp_point_write_binary +#define ecp_self_test mbedtls_ecp_self_test +#define ecp_set_zero mbedtls_ecp_set_zero +#define ecp_tls_read_group mbedtls_ecp_tls_read_group +#define ecp_tls_read_point mbedtls_ecp_tls_read_point +#define ecp_tls_write_group mbedtls_ecp_tls_write_group +#define ecp_tls_write_point mbedtls_ecp_tls_write_point +#define ecp_use_known_dp mbedtls_ecp_group_load +#define entropy_add_source mbedtls_entropy_add_source +#define entropy_context mbedtls_entropy_context +#define entropy_free mbedtls_entropy_free +#define entropy_func mbedtls_entropy_func +#define entropy_gather mbedtls_entropy_gather +#define entropy_init mbedtls_entropy_init +#define entropy_self_test mbedtls_entropy_self_test +#define entropy_update_manual mbedtls_entropy_update_manual +#define entropy_update_seed_file mbedtls_entropy_update_seed_file +#define entropy_write_seed_file mbedtls_entropy_write_seed_file +#define error_strerror mbedtls_strerror +#define f_source_ptr mbedtls_entropy_f_source_ptr +#define gcm_auth_decrypt mbedtls_gcm_auth_decrypt +#define gcm_context mbedtls_gcm_context +#define gcm_crypt_and_tag mbedtls_gcm_crypt_and_tag +#define gcm_finish mbedtls_gcm_finish +#define gcm_free mbedtls_gcm_free +#define gcm_init mbedtls_gcm_init +#define gcm_self_test mbedtls_gcm_self_test +#define gcm_starts mbedtls_gcm_starts +#define gcm_update mbedtls_gcm_update +#define get_timer mbedtls_timing_get_timer +#define hardclock mbedtls_timing_hardclock +#define hardclock_poll mbedtls_hardclock_poll +#define havege_free mbedtls_havege_free +#define havege_init mbedtls_havege_init +#define havege_poll mbedtls_havege_poll +#define havege_random mbedtls_havege_random +#define havege_state mbedtls_havege_state +#define hmac_drbg_context mbedtls_hmac_drbg_context +#define hmac_drbg_free mbedtls_hmac_drbg_free +#define hmac_drbg_init mbedtls_hmac_drbg_init +#define hmac_drbg_random mbedtls_hmac_drbg_random +#define hmac_drbg_random_with_add mbedtls_hmac_drbg_random_with_add +#define hmac_drbg_reseed mbedtls_hmac_drbg_reseed +#define hmac_drbg_self_test mbedtls_hmac_drbg_self_test +#define hmac_drbg_set_entropy_len mbedtls_hmac_drbg_set_entropy_len +#define hmac_drbg_set_prediction_resistance mbedtls_hmac_drbg_set_prediction_resistance +#define hmac_drbg_set_reseed_interval mbedtls_hmac_drbg_set_reseed_interval +#define hmac_drbg_update mbedtls_hmac_drbg_update +#define hmac_drbg_update_seed_file mbedtls_hmac_drbg_update_seed_file +#define hmac_drbg_write_seed_file mbedtls_hmac_drbg_write_seed_file +#define hr_time mbedtls_timing_hr_time +#define key_exchange_type_t mbedtls_key_exchange_type_t +#define md mbedtls_md +#define md2 mbedtls_md2 +#define md2_context mbedtls_md2_context +#define md2_finish mbedtls_md2_finish +#define md2_free mbedtls_md2_free +#define md2_info mbedtls_md2_info +#define md2_init mbedtls_md2_init +#define md2_process mbedtls_md2_process +#define md2_self_test mbedtls_md2_self_test +#define md2_starts mbedtls_md2_starts +#define md2_update mbedtls_md2_update +#define md4 mbedtls_md4 +#define md4_context mbedtls_md4_context +#define md4_finish mbedtls_md4_finish +#define md4_free mbedtls_md4_free +#define md4_info mbedtls_md4_info +#define md4_init mbedtls_md4_init +#define md4_process mbedtls_md4_process +#define md4_self_test mbedtls_md4_self_test +#define md4_starts mbedtls_md4_starts +#define md4_update mbedtls_md4_update +#define md5 mbedtls_md5 +#define md5_context mbedtls_md5_context +#define md5_finish mbedtls_md5_finish +#define md5_free mbedtls_md5_free +#define md5_info mbedtls_md5_info +#define md5_init mbedtls_md5_init +#define md5_process mbedtls_md5_process +#define md5_self_test mbedtls_md5_self_test +#define md5_starts mbedtls_md5_starts +#define md5_update mbedtls_md5_update +#define md_context_t mbedtls_md_context_t +#define md_file mbedtls_md_file +#define md_finish mbedtls_md_finish +#define md_free mbedtls_md_free +#define md_get_name mbedtls_md_get_name +#define md_get_size mbedtls_md_get_size +#define md_get_type mbedtls_md_get_type +#define md_hmac mbedtls_md_hmac +#define md_hmac_finish mbedtls_md_hmac_finish +#define md_hmac_reset mbedtls_md_hmac_reset +#define md_hmac_starts mbedtls_md_hmac_starts +#define md_hmac_update mbedtls_md_hmac_update +#define md_info_from_string mbedtls_md_info_from_string +#define md_info_from_type mbedtls_md_info_from_type +#define md_info_t mbedtls_md_info_t +#define md_init mbedtls_md_init +#define md_init_ctx mbedtls_md_init_ctx +#define md_list mbedtls_md_list +#define md_process mbedtls_md_process +#define md_starts mbedtls_md_starts +#define md_type_t mbedtls_md_type_t +#define md_update mbedtls_md_update +#define memory_buffer_alloc_cur_get mbedtls_memory_buffer_alloc_cur_get +#define memory_buffer_alloc_free mbedtls_memory_buffer_alloc_free +#define memory_buffer_alloc_init mbedtls_memory_buffer_alloc_init +#define memory_buffer_alloc_max_get mbedtls_memory_buffer_alloc_max_get +#define memory_buffer_alloc_max_reset mbedtls_memory_buffer_alloc_max_reset +#define memory_buffer_alloc_self_test mbedtls_memory_buffer_alloc_self_test +#define memory_buffer_alloc_status mbedtls_memory_buffer_alloc_status +#define memory_buffer_alloc_verify mbedtls_memory_buffer_alloc_verify +#define memory_buffer_set_verify mbedtls_memory_buffer_set_verify +#define mpi mbedtls_mpi +#define mpi_add_abs mbedtls_mpi_add_abs +#define mpi_add_int mbedtls_mpi_add_int +#define mpi_add_mpi mbedtls_mpi_add_mpi +#define mpi_cmp_abs mbedtls_mpi_cmp_abs +#define mpi_cmp_int mbedtls_mpi_cmp_int +#define mpi_cmp_mpi mbedtls_mpi_cmp_mpi +#define mpi_copy mbedtls_mpi_copy +#define mpi_div_int mbedtls_mpi_div_int +#define mpi_div_mpi mbedtls_mpi_div_mpi +#define mpi_exp_mod mbedtls_mpi_exp_mod +#define mpi_fill_random mbedtls_mpi_fill_random +#define mpi_free mbedtls_mpi_free +#define mpi_gcd mbedtls_mpi_gcd +#define mpi_gen_prime mbedtls_mpi_gen_prime +#define mpi_get_bit mbedtls_mpi_get_bit +#define mpi_grow mbedtls_mpi_grow +#define mpi_init mbedtls_mpi_init +#define mpi_inv_mod mbedtls_mpi_inv_mod +#define mpi_is_prime mbedtls_mpi_is_prime +#define mpi_lsb mbedtls_mpi_lsb +#define mpi_lset mbedtls_mpi_lset +#define mpi_mod_int mbedtls_mpi_mod_int +#define mpi_mod_mpi mbedtls_mpi_mod_mpi +#define mpi_msb mbedtls_mpi_bitlen +#define mpi_mul_int mbedtls_mpi_mul_int +#define mpi_mul_mpi mbedtls_mpi_mul_mpi +#define mpi_read_binary mbedtls_mpi_read_binary +#define mpi_read_file mbedtls_mpi_read_file +#define mpi_read_string mbedtls_mpi_read_string +#define mpi_safe_cond_assign mbedtls_mpi_safe_cond_assign +#define mpi_safe_cond_swap mbedtls_mpi_safe_cond_swap +#define mpi_self_test mbedtls_mpi_self_test +#define mpi_set_bit mbedtls_mpi_set_bit +#define mpi_shift_l mbedtls_mpi_shift_l +#define mpi_shift_r mbedtls_mpi_shift_r +#define mpi_shrink mbedtls_mpi_shrink +#define mpi_size mbedtls_mpi_size +#define mpi_sub_abs mbedtls_mpi_sub_abs +#define mpi_sub_int mbedtls_mpi_sub_int +#define mpi_sub_mpi mbedtls_mpi_sub_mpi +#define mpi_swap mbedtls_mpi_swap +#define mpi_write_binary mbedtls_mpi_write_binary +#define mpi_write_file mbedtls_mpi_write_file +#define mpi_write_string mbedtls_mpi_write_string +#define net_accept mbedtls_net_accept +#define net_bind mbedtls_net_bind +#define net_close mbedtls_net_free +#define net_connect mbedtls_net_connect +#define net_recv mbedtls_net_recv +#define net_recv_timeout mbedtls_net_recv_timeout +#define net_send mbedtls_net_send +#define net_set_block mbedtls_net_set_block +#define net_set_nonblock mbedtls_net_set_nonblock +#define net_usleep mbedtls_net_usleep +#define oid_descriptor_t mbedtls_oid_descriptor_t +#define oid_get_attr_short_name mbedtls_oid_get_attr_short_name +#define oid_get_cipher_alg mbedtls_oid_get_cipher_alg +#define oid_get_ec_grp mbedtls_oid_get_ec_grp +#define oid_get_extended_key_usage mbedtls_oid_get_extended_key_usage +#define oid_get_md_alg mbedtls_oid_get_md_alg +#define oid_get_numeric_string mbedtls_oid_get_numeric_string +#define oid_get_oid_by_ec_grp mbedtls_oid_get_oid_by_ec_grp +#define oid_get_oid_by_md mbedtls_oid_get_oid_by_md +#define oid_get_oid_by_pk_alg mbedtls_oid_get_oid_by_pk_alg +#define oid_get_oid_by_sig_alg mbedtls_oid_get_oid_by_sig_alg +#define oid_get_pk_alg mbedtls_oid_get_pk_alg +#define oid_get_pkcs12_pbe_alg mbedtls_oid_get_pkcs12_pbe_alg +#define oid_get_sig_alg mbedtls_oid_get_sig_alg +#define oid_get_sig_alg_desc mbedtls_oid_get_sig_alg_desc +#define oid_get_x509_ext_type mbedtls_oid_get_x509_ext_type +#define operation_t mbedtls_operation_t +#define padlock_supports mbedtls_padlock_has_support +#define padlock_xcryptcbc mbedtls_padlock_xcryptcbc +#define padlock_xcryptecb mbedtls_padlock_xcryptecb +#define pem_context mbedtls_pem_context +#define pem_free mbedtls_pem_free +#define pem_init mbedtls_pem_init +#define pem_read_buffer mbedtls_pem_read_buffer +#define pem_write_buffer mbedtls_pem_write_buffer +#define pk_can_do mbedtls_pk_can_do +#define pk_check_pair mbedtls_pk_check_pair +#define pk_context mbedtls_pk_context +#define pk_debug mbedtls_pk_debug +#define pk_debug_item mbedtls_pk_debug_item +#define pk_debug_type mbedtls_pk_debug_type +#define pk_decrypt mbedtls_pk_decrypt +#define pk_ec mbedtls_pk_ec +#define pk_encrypt mbedtls_pk_encrypt +#define pk_free mbedtls_pk_free +#define pk_get_len mbedtls_pk_get_len +#define pk_get_name mbedtls_pk_get_name +#define pk_get_size mbedtls_pk_get_bitlen +#define pk_get_type mbedtls_pk_get_type +#define pk_info_from_type mbedtls_pk_info_from_type +#define pk_info_t mbedtls_pk_info_t +#define pk_init mbedtls_pk_init +#define pk_init_ctx mbedtls_pk_setup +#define pk_init_ctx_rsa_alt mbedtls_pk_setup_rsa_alt +#define pk_load_file mbedtls_pk_load_file +#define pk_parse_key mbedtls_pk_parse_key +#define pk_parse_keyfile mbedtls_pk_parse_keyfile +#define pk_parse_public_key mbedtls_pk_parse_public_key +#define pk_parse_public_keyfile mbedtls_pk_parse_public_keyfile +#define pk_parse_subpubkey mbedtls_pk_parse_subpubkey +#define pk_rsa mbedtls_pk_rsa +#define pk_rsa_alt_decrypt_func mbedtls_pk_rsa_alt_decrypt_func +#define pk_rsa_alt_key_len_func mbedtls_pk_rsa_alt_key_len_func +#define pk_rsa_alt_sign_func mbedtls_pk_rsa_alt_sign_func +#define pk_rsassa_pss_options mbedtls_pk_rsassa_pss_options +#define pk_sign mbedtls_pk_sign +#define pk_type_t mbedtls_pk_type_t +#define pk_verify mbedtls_pk_verify +#define pk_verify_ext mbedtls_pk_verify_ext +#define pk_write_key_der mbedtls_pk_write_key_der +#define pk_write_key_pem mbedtls_pk_write_key_pem +#define pk_write_pubkey mbedtls_pk_write_pubkey +#define pk_write_pubkey_der mbedtls_pk_write_pubkey_der +#define pk_write_pubkey_pem mbedtls_pk_write_pubkey_pem +#define pkcs11_context mbedtls_pkcs11_context +#define pkcs11_decrypt mbedtls_pkcs11_decrypt +#define pkcs11_priv_key_free mbedtls_pkcs11_priv_key_free +#define pkcs11_priv_key_init mbedtls_pkcs11_priv_key_bind +#define pkcs11_sign mbedtls_pkcs11_sign +#define pkcs11_x509_cert_init mbedtls_pkcs11_x509_cert_bind +#define pkcs12_derivation mbedtls_pkcs12_derivation +#define pkcs12_pbe mbedtls_pkcs12_pbe +#define pkcs12_pbe_sha1_rc4_128 mbedtls_pkcs12_pbe_sha1_rc4_128 +#define pkcs5_pbes2 mbedtls_pkcs5_pbes2 +#define pkcs5_pbkdf2_hmac mbedtls_pkcs5_pbkdf2_hmac +#define pkcs5_self_test mbedtls_pkcs5_self_test +#define platform_entropy_poll mbedtls_platform_entropy_poll +#define platform_set_exit mbedtls_platform_set_exit +#define platform_set_fprintf mbedtls_platform_set_fprintf +#define platform_set_printf mbedtls_platform_set_printf +#define platform_set_snprintf mbedtls_platform_set_snprintf +#define polarssl_exit mbedtls_exit +#define polarssl_fprintf mbedtls_fprintf +#define polarssl_free mbedtls_free +#define polarssl_mutex_free mbedtls_mutex_free +#define polarssl_mutex_init mbedtls_mutex_init +#define polarssl_mutex_lock mbedtls_mutex_lock +#define polarssl_mutex_unlock mbedtls_mutex_unlock +#define polarssl_printf mbedtls_printf +#define polarssl_snprintf mbedtls_snprintf +#define polarssl_strerror mbedtls_strerror +#define ripemd160 mbedtls_ripemd160 +#define ripemd160_context mbedtls_ripemd160_context +#define ripemd160_finish mbedtls_ripemd160_finish +#define ripemd160_free mbedtls_ripemd160_free +#define ripemd160_info mbedtls_ripemd160_info +#define ripemd160_init mbedtls_ripemd160_init +#define ripemd160_process mbedtls_ripemd160_process +#define ripemd160_self_test mbedtls_ripemd160_self_test +#define ripemd160_starts mbedtls_ripemd160_starts +#define ripemd160_update mbedtls_ripemd160_update +#define rsa_alt_context mbedtls_rsa_alt_context +#define rsa_alt_info mbedtls_rsa_alt_info +#define rsa_check_privkey mbedtls_rsa_check_privkey +#define rsa_check_pub_priv mbedtls_rsa_check_pub_priv +#define rsa_check_pubkey mbedtls_rsa_check_pubkey +#define rsa_context mbedtls_rsa_context +#define rsa_copy mbedtls_rsa_copy +#define rsa_free mbedtls_rsa_free +#define rsa_gen_key mbedtls_rsa_gen_key +#define rsa_info mbedtls_rsa_info +#define rsa_init mbedtls_rsa_init +#define rsa_pkcs1_decrypt mbedtls_rsa_pkcs1_decrypt +#define rsa_pkcs1_encrypt mbedtls_rsa_pkcs1_encrypt +#define rsa_pkcs1_sign mbedtls_rsa_pkcs1_sign +#define rsa_pkcs1_verify mbedtls_rsa_pkcs1_verify +#define rsa_private mbedtls_rsa_private +#define rsa_public mbedtls_rsa_public +#define rsa_rsaes_oaep_decrypt mbedtls_rsa_rsaes_oaep_decrypt +#define rsa_rsaes_oaep_encrypt mbedtls_rsa_rsaes_oaep_encrypt +#define rsa_rsaes_pkcs1_v15_decrypt mbedtls_rsa_rsaes_pkcs1_v15_decrypt +#define rsa_rsaes_pkcs1_v15_encrypt mbedtls_rsa_rsaes_pkcs1_v15_encrypt +#define rsa_rsassa_pkcs1_v15_sign mbedtls_rsa_rsassa_pkcs1_v15_sign +#define rsa_rsassa_pkcs1_v15_verify mbedtls_rsa_rsassa_pkcs1_v15_verify +#define rsa_rsassa_pss_sign mbedtls_rsa_rsassa_pss_sign +#define rsa_rsassa_pss_verify mbedtls_rsa_rsassa_pss_verify +#define rsa_rsassa_pss_verify_ext mbedtls_rsa_rsassa_pss_verify_ext +#define rsa_self_test mbedtls_rsa_self_test +#define rsa_set_padding mbedtls_rsa_set_padding +#define safer_memcmp mbedtls_ssl_safer_memcmp +#define set_alarm mbedtls_set_alarm +#define sha1 mbedtls_sha1 +#define sha1_context mbedtls_sha1_context +#define sha1_finish mbedtls_sha1_finish +#define sha1_free mbedtls_sha1_free +#define sha1_info mbedtls_sha1_info +#define sha1_init mbedtls_sha1_init +#define sha1_process mbedtls_sha1_process +#define sha1_self_test mbedtls_sha1_self_test +#define sha1_starts mbedtls_sha1_starts +#define sha1_update mbedtls_sha1_update +#define sha224_info mbedtls_sha224_info +#define sha256 mbedtls_sha256 +#define sha256_context mbedtls_sha256_context +#define sha256_finish mbedtls_sha256_finish +#define sha256_free mbedtls_sha256_free +#define sha256_info mbedtls_sha256_info +#define sha256_init mbedtls_sha256_init +#define sha256_process mbedtls_sha256_process +#define sha256_self_test mbedtls_sha256_self_test +#define sha256_starts mbedtls_sha256_starts +#define sha256_update mbedtls_sha256_update +#define sha384_info mbedtls_sha384_info +#define sha512 mbedtls_sha512 +#define sha512_context mbedtls_sha512_context +#define sha512_finish mbedtls_sha512_finish +#define sha512_free mbedtls_sha512_free +#define sha512_info mbedtls_sha512_info +#define sha512_init mbedtls_sha512_init +#define sha512_process mbedtls_sha512_process +#define sha512_self_test mbedtls_sha512_self_test +#define sha512_starts mbedtls_sha512_starts +#define sha512_update mbedtls_sha512_update +#define source_state mbedtls_entropy_source_state +#define ssl_cache_context mbedtls_ssl_cache_context +#define ssl_cache_entry mbedtls_ssl_cache_entry +#define ssl_cache_free mbedtls_ssl_cache_free +#define ssl_cache_get mbedtls_ssl_cache_get +#define ssl_cache_init mbedtls_ssl_cache_init +#define ssl_cache_set mbedtls_ssl_cache_set +#define ssl_cache_set_max_entries mbedtls_ssl_cache_set_max_entries +#define ssl_cache_set_timeout mbedtls_ssl_cache_set_timeout +#define ssl_check_cert_usage mbedtls_ssl_check_cert_usage +#define ssl_ciphersuite_from_id mbedtls_ssl_ciphersuite_from_id +#define ssl_ciphersuite_from_string mbedtls_ssl_ciphersuite_from_string +#define ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t +#define ssl_ciphersuite_uses_ec mbedtls_ssl_ciphersuite_uses_ec +#define ssl_ciphersuite_uses_psk mbedtls_ssl_ciphersuite_uses_psk +#define ssl_close_notify mbedtls_ssl_close_notify +#define ssl_context mbedtls_ssl_context +#define ssl_cookie_check mbedtls_ssl_cookie_check +#define ssl_cookie_check_t mbedtls_ssl_cookie_check_t +#define ssl_cookie_ctx mbedtls_ssl_cookie_ctx +#define ssl_cookie_free mbedtls_ssl_cookie_free +#define ssl_cookie_init mbedtls_ssl_cookie_init +#define ssl_cookie_set_timeout mbedtls_ssl_cookie_set_timeout +#define ssl_cookie_setup mbedtls_ssl_cookie_setup +#define ssl_cookie_write mbedtls_ssl_cookie_write +#define ssl_cookie_write_t mbedtls_ssl_cookie_write_t +#define ssl_derive_keys mbedtls_ssl_derive_keys +#define ssl_dtls_replay_check mbedtls_ssl_dtls_replay_check +#define ssl_dtls_replay_update mbedtls_ssl_dtls_replay_update +#define ssl_fetch_input mbedtls_ssl_fetch_input +#define ssl_flight_item mbedtls_ssl_flight_item +#define ssl_flush_output mbedtls_ssl_flush_output +#define ssl_free mbedtls_ssl_free +#define ssl_get_alpn_protocol mbedtls_ssl_get_alpn_protocol +#define ssl_get_bytes_avail mbedtls_ssl_get_bytes_avail +#define ssl_get_ciphersuite mbedtls_ssl_get_ciphersuite +#define ssl_get_ciphersuite_id mbedtls_ssl_get_ciphersuite_id +#define ssl_get_ciphersuite_name mbedtls_ssl_get_ciphersuite_name +#define ssl_get_ciphersuite_sig_pk_alg mbedtls_ssl_get_ciphersuite_sig_pk_alg +#define ssl_get_peer_cert mbedtls_ssl_get_peer_cert +#define ssl_get_record_expansion mbedtls_ssl_get_record_expansion +#define ssl_get_session mbedtls_ssl_get_session +#define ssl_get_verify_result mbedtls_ssl_get_verify_result +#define ssl_get_version mbedtls_ssl_get_version +#define ssl_handshake mbedtls_ssl_handshake +#define ssl_handshake_client_step mbedtls_ssl_handshake_client_step +#define ssl_handshake_free mbedtls_ssl_handshake_free +#define ssl_handshake_params mbedtls_ssl_handshake_params +#define ssl_handshake_server_step mbedtls_ssl_handshake_server_step +#define ssl_handshake_step mbedtls_ssl_handshake_step +#define ssl_handshake_wrapup mbedtls_ssl_handshake_wrapup +#define ssl_hdr_len mbedtls_ssl_hdr_len +#define ssl_hs_hdr_len mbedtls_ssl_hs_hdr_len +#define ssl_hw_record_activate mbedtls_ssl_hw_record_activate +#define ssl_hw_record_finish mbedtls_ssl_hw_record_finish +#define ssl_hw_record_init mbedtls_ssl_hw_record_init +#define ssl_hw_record_read mbedtls_ssl_hw_record_read +#define ssl_hw_record_reset mbedtls_ssl_hw_record_reset +#define ssl_hw_record_write mbedtls_ssl_hw_record_write +#define ssl_init mbedtls_ssl_init +#define ssl_key_cert mbedtls_ssl_key_cert +#define ssl_legacy_renegotiation mbedtls_ssl_conf_legacy_renegotiation +#define ssl_list_ciphersuites mbedtls_ssl_list_ciphersuites +#define ssl_md_alg_from_hash mbedtls_ssl_md_alg_from_hash +#define ssl_optimize_checksum mbedtls_ssl_optimize_checksum +#define ssl_own_cert mbedtls_ssl_own_cert +#define ssl_own_key mbedtls_ssl_own_key +#define ssl_parse_certificate mbedtls_ssl_parse_certificate +#define ssl_parse_change_cipher_spec mbedtls_ssl_parse_change_cipher_spec +#define ssl_parse_finished mbedtls_ssl_parse_finished +#define ssl_pk_alg_from_sig mbedtls_ssl_pk_alg_from_sig +#define ssl_pkcs11_decrypt mbedtls_ssl_pkcs11_decrypt +#define ssl_pkcs11_key_len mbedtls_ssl_pkcs11_key_len +#define ssl_pkcs11_sign mbedtls_ssl_pkcs11_sign +#define ssl_psk_derive_premaster mbedtls_ssl_psk_derive_premaster +#define ssl_read mbedtls_ssl_read +#define ssl_read_record mbedtls_ssl_read_record +#define ssl_read_version mbedtls_ssl_read_version +#define ssl_recv_flight_completed mbedtls_ssl_recv_flight_completed +#define ssl_renegotiate mbedtls_ssl_renegotiate +#define ssl_resend mbedtls_ssl_resend +#define ssl_reset_checksum mbedtls_ssl_reset_checksum +#define ssl_send_alert_message mbedtls_ssl_send_alert_message +#define ssl_send_fatal_handshake_failure mbedtls_ssl_send_fatal_handshake_failure +#define ssl_send_flight_completed mbedtls_ssl_send_flight_completed +#define ssl_session mbedtls_ssl_session +#define ssl_session_free mbedtls_ssl_session_free +#define ssl_session_init mbedtls_ssl_session_init +#define ssl_session_reset mbedtls_ssl_session_reset +#define ssl_set_alpn_protocols mbedtls_ssl_conf_alpn_protocols +#define ssl_set_arc4_support mbedtls_ssl_conf_arc4_support +#define ssl_set_authmode mbedtls_ssl_conf_authmode +#define ssl_set_bio mbedtls_ssl_set_bio +#define ssl_set_ca_chain mbedtls_ssl_conf_ca_chain +#define ssl_set_cbc_record_splitting mbedtls_ssl_conf_cbc_record_splitting +#define ssl_set_ciphersuites mbedtls_ssl_conf_ciphersuites +#define ssl_set_ciphersuites_for_version mbedtls_ssl_conf_ciphersuites_for_version +#define ssl_set_client_transport_id mbedtls_ssl_set_client_transport_id +#define ssl_set_curves mbedtls_ssl_conf_curves +#define ssl_set_dbg mbedtls_ssl_conf_dbg +#define ssl_set_dh_param mbedtls_ssl_conf_dh_param +#define ssl_set_dh_param_ctx mbedtls_ssl_conf_dh_param_ctx +#define ssl_set_dtls_anti_replay mbedtls_ssl_conf_dtls_anti_replay +#define ssl_set_dtls_badmac_limit mbedtls_ssl_conf_dtls_badmac_limit +#define ssl_set_dtls_cookies mbedtls_ssl_conf_dtls_cookies +#define ssl_set_encrypt_then_mac mbedtls_ssl_conf_encrypt_then_mac +#define ssl_set_endpoint mbedtls_ssl_conf_endpoint +#define ssl_set_extended_master_secret mbedtls_ssl_conf_extended_master_secret +#define ssl_set_fallback mbedtls_ssl_conf_fallback +#define ssl_set_handshake_timeout mbedtls_ssl_conf_handshake_timeout +#define ssl_set_hostname mbedtls_ssl_set_hostname +#define ssl_set_max_frag_len mbedtls_ssl_conf_max_frag_len +#define ssl_set_max_version mbedtls_ssl_conf_max_version +#define ssl_set_min_version mbedtls_ssl_conf_min_version +#define ssl_set_own_cert mbedtls_ssl_conf_own_cert +#define ssl_set_psk mbedtls_ssl_conf_psk +#define ssl_set_psk_cb mbedtls_ssl_conf_psk_cb +#define ssl_set_renegotiation mbedtls_ssl_conf_renegotiation +#define ssl_set_renegotiation_enforced mbedtls_ssl_conf_renegotiation_enforced +#define ssl_set_renegotiation_period mbedtls_ssl_conf_renegotiation_period +#define ssl_set_rng mbedtls_ssl_conf_rng +#define ssl_set_session mbedtls_ssl_set_session +#define ssl_set_session_cache mbedtls_ssl_conf_session_cache +#define ssl_set_session_tickets mbedtls_ssl_conf_session_tickets +#define ssl_set_sni mbedtls_ssl_conf_sni +#define ssl_set_transport mbedtls_ssl_conf_transport +#define ssl_set_truncated_hmac mbedtls_ssl_conf_truncated_hmac +#define ssl_set_verify mbedtls_ssl_conf_verify +#define ssl_sig_from_pk mbedtls_ssl_sig_from_pk +#define ssl_states mbedtls_ssl_states +#define ssl_transform mbedtls_ssl_transform +#define ssl_transform_free mbedtls_ssl_transform_free +#define ssl_write mbedtls_ssl_write +#define ssl_write_certificate mbedtls_ssl_write_certificate +#define ssl_write_change_cipher_spec mbedtls_ssl_write_change_cipher_spec +#define ssl_write_finished mbedtls_ssl_write_finished +#define ssl_write_record mbedtls_ssl_write_record +#define ssl_write_version mbedtls_ssl_write_version +#define supported_ciphers mbedtls_cipher_supported +#define t_sint mbedtls_mpi_sint +#define t_udbl mbedtls_t_udbl +#define t_uint mbedtls_mpi_uint +#define test_ca_crt mbedtls_test_ca_crt +#define test_ca_crt_ec mbedtls_test_ca_crt_ec +#define test_ca_crt_rsa mbedtls_test_ca_crt_rsa +#define test_ca_key mbedtls_test_ca_key +#define test_ca_key_ec mbedtls_test_ca_key_ec +#define test_ca_key_rsa mbedtls_test_ca_key_rsa +#define test_ca_list mbedtls_test_cas_pem +#define test_ca_pwd mbedtls_test_ca_pwd +#define test_ca_pwd_ec mbedtls_test_ca_pwd_ec +#define test_ca_pwd_rsa mbedtls_test_ca_pwd_rsa +#define test_cli_crt mbedtls_test_cli_crt +#define test_cli_crt_ec mbedtls_test_cli_crt_ec +#define test_cli_crt_rsa mbedtls_test_cli_crt_rsa +#define test_cli_key mbedtls_test_cli_key +#define test_cli_key_ec mbedtls_test_cli_key_ec +#define test_cli_key_rsa mbedtls_test_cli_key_rsa +#define test_srv_crt mbedtls_test_srv_crt +#define test_srv_crt_ec mbedtls_test_srv_crt_ec +#define test_srv_crt_rsa mbedtls_test_srv_crt_rsa +#define test_srv_key mbedtls_test_srv_key +#define test_srv_key_ec mbedtls_test_srv_key_ec +#define test_srv_key_rsa mbedtls_test_srv_key_rsa +#define threading_mutex_t mbedtls_threading_mutex_t +#define threading_set_alt mbedtls_threading_set_alt +#define timing_self_test mbedtls_timing_self_test +#define version_check_feature mbedtls_version_check_feature +#define version_get_number mbedtls_version_get_number +#define version_get_string mbedtls_version_get_string +#define version_get_string_full mbedtls_version_get_string_full +#define x509_bitstring mbedtls_x509_bitstring +#define x509_buf mbedtls_x509_buf +#define x509_crl mbedtls_x509_crl +#define x509_crl_entry mbedtls_x509_crl_entry +#define x509_crl_free mbedtls_x509_crl_free +#define x509_crl_info mbedtls_x509_crl_info +#define x509_crl_init mbedtls_x509_crl_init +#define x509_crl_parse mbedtls_x509_crl_parse +#define x509_crl_parse_der mbedtls_x509_crl_parse_der +#define x509_crl_parse_file mbedtls_x509_crl_parse_file +#define x509_crt mbedtls_x509_crt +#define x509_crt_check_extended_key_usage mbedtls_x509_crt_check_extended_key_usage +#define x509_crt_check_key_usage mbedtls_x509_crt_check_key_usage +#define x509_crt_free mbedtls_x509_crt_free +#define x509_crt_info mbedtls_x509_crt_info +#define x509_crt_init mbedtls_x509_crt_init +#define x509_crt_parse mbedtls_x509_crt_parse +#define x509_crt_parse_der mbedtls_x509_crt_parse_der +#define x509_crt_parse_file mbedtls_x509_crt_parse_file +#define x509_crt_parse_path mbedtls_x509_crt_parse_path +#define x509_crt_revoked mbedtls_x509_crt_is_revoked +#define x509_crt_verify mbedtls_x509_crt_verify +#define x509_csr mbedtls_x509_csr +#define x509_csr_free mbedtls_x509_csr_free +#define x509_csr_info mbedtls_x509_csr_info +#define x509_csr_init mbedtls_x509_csr_init +#define x509_csr_parse mbedtls_x509_csr_parse +#define x509_csr_parse_der mbedtls_x509_csr_parse_der +#define x509_csr_parse_file mbedtls_x509_csr_parse_file +#define x509_dn_gets mbedtls_x509_dn_gets +#define x509_get_alg mbedtls_x509_get_alg +#define x509_get_alg_null mbedtls_x509_get_alg_null +#define x509_get_ext mbedtls_x509_get_ext +#define x509_get_name mbedtls_x509_get_name +#define x509_get_rsassa_pss_params mbedtls_x509_get_rsassa_pss_params +#define x509_get_serial mbedtls_x509_get_serial +#define x509_get_sig mbedtls_x509_get_sig +#define x509_get_sig_alg mbedtls_x509_get_sig_alg +#define x509_get_time mbedtls_x509_get_time +#define x509_key_size_helper mbedtls_x509_key_size_helper +#define x509_name mbedtls_x509_name +#define x509_self_test mbedtls_x509_self_test +#define x509_sequence mbedtls_x509_sequence +#define x509_serial_gets mbedtls_x509_serial_gets +#define x509_set_extension mbedtls_x509_set_extension +#define x509_sig_alg_gets mbedtls_x509_sig_alg_gets +#define x509_string_to_names mbedtls_x509_string_to_names +#define x509_time mbedtls_x509_time +#define x509_time_expired mbedtls_x509_time_is_past +#define x509_time_future mbedtls_x509_time_is_future +#define x509_write_extensions mbedtls_x509_write_extensions +#define x509_write_names mbedtls_x509_write_names +#define x509_write_sig mbedtls_x509_write_sig +#define x509write_cert mbedtls_x509write_cert +#define x509write_crt_der mbedtls_x509write_crt_der +#define x509write_crt_free mbedtls_x509write_crt_free +#define x509write_crt_init mbedtls_x509write_crt_init +#define x509write_crt_pem mbedtls_x509write_crt_pem +#define x509write_crt_set_authority_key_identifier mbedtls_x509write_crt_set_authority_key_identifier +#define x509write_crt_set_basic_constraints mbedtls_x509write_crt_set_basic_constraints +#define x509write_crt_set_extension mbedtls_x509write_crt_set_extension +#define x509write_crt_set_issuer_key mbedtls_x509write_crt_set_issuer_key +#define x509write_crt_set_issuer_name mbedtls_x509write_crt_set_issuer_name +#define x509write_crt_set_key_usage mbedtls_x509write_crt_set_key_usage +#define x509write_crt_set_md_alg mbedtls_x509write_crt_set_md_alg +#define x509write_crt_set_ns_cert_type mbedtls_x509write_crt_set_ns_cert_type +#define x509write_crt_set_serial mbedtls_x509write_crt_set_serial +#define x509write_crt_set_subject_key mbedtls_x509write_crt_set_subject_key +#define x509write_crt_set_subject_key_identifier mbedtls_x509write_crt_set_subject_key_identifier +#define x509write_crt_set_subject_name mbedtls_x509write_crt_set_subject_name +#define x509write_crt_set_validity mbedtls_x509write_crt_set_validity +#define x509write_crt_set_version mbedtls_x509write_crt_set_version +#define x509write_csr mbedtls_x509write_csr +#define x509write_csr_der mbedtls_x509write_csr_der +#define x509write_csr_free mbedtls_x509write_csr_free +#define x509write_csr_init mbedtls_x509write_csr_init +#define x509write_csr_pem mbedtls_x509write_csr_pem +#define x509write_csr_set_extension mbedtls_x509write_csr_set_extension +#define x509write_csr_set_key mbedtls_x509write_csr_set_key +#define x509write_csr_set_key_usage mbedtls_x509write_csr_set_key_usage +#define x509write_csr_set_md_alg mbedtls_x509write_csr_set_md_alg +#define x509write_csr_set_ns_cert_type mbedtls_x509write_csr_set_ns_cert_type +#define x509write_csr_set_subject_name mbedtls_x509write_csr_set_subject_name +#define xtea_context mbedtls_xtea_context +#define xtea_crypt_cbc mbedtls_xtea_crypt_cbc +#define xtea_crypt_ecb mbedtls_xtea_crypt_ecb +#define xtea_free mbedtls_xtea_free +#define xtea_init mbedtls_xtea_init +#define xtea_self_test mbedtls_xtea_self_test +#define xtea_setup mbedtls_xtea_setup + +#endif /* compat-1.3.h */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/config.h b/third-party/mbedtls-3.6/include/mbedtls/config.h new file mode 100644 index 00000000..a1b2d77f --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/config.h @@ -0,0 +1,2976 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#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 necessarily 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 overridden, 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. + * + * \warning If both MBEDTLS_ECDSA_SIGN_ALT and MBEDTLS_ECDSA_DETERMINISTIC are + * enabled, then the deterministic ECDH signature functions pass the + * the static HMAC-DRBG as RNG to mbedtls_ecdsa_sign(). Therefore + * alternative implementations should use the RNG only for generating + * the ephemeral key and nothing else. If this is not possible, then + * MBEDTLS_ECDSA_DETERMINISTIC should be disabled and an alternative + * implementation should be provided for mbedtls_ecdsa_sign_det_ext() + * (and for mbedtls_ecdsa_sign_det() too if backward compatibility is + * desirable). + * + */ +//#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_CONSTANT_FLOW_MEMSAN + * + * Enable testing of the constant-flow nature of some sensitive functions with + * clang's MemorySanitizer. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires compiling with clang -fsanitize=memory. The test + * suites can then be run normally. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN + +/** + * \def MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + * + * Enable testing of the constant-flow nature of some sensitive functions with + * valgrind's memcheck tool. This causes some existing tests to also test + * this non-functional property of the code under test. + * + * This setting requires valgrind headers for building, and is only useful for + * testing if the tests suites are run with valgrind's memcheck. This can be + * done for an individual test suite with 'valgrind ./test_suite_xxx', or when + * using CMake, this can be done for all test suites with 'make memcheck'. + * + * \warning This macro is only used for extended testing; it is not considered + * part of the library's API, so it may change or disappear at any time. + * + * Uncomment to enable testing of the constant-flow nature of selected code. + */ +//#define MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND + +/** + * \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_REMOVE_3DES_CIPHERSUITES + * + * Remove 3DES ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on 3DES 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. + * + * A man-in-the-browser attacker can recover authentication tokens sent through + * a TLS connection using a 3DES based cipher suite (see "On the Practical + * (In-)Security of 64-bit Block Ciphers" by Karthikeyan Bhargavan and Gaëtan + * Leurent, see https://sweet32.info/SWEET32_CCS16.pdf). If this attack falls + * in your threat model or you are unsure, then you should keep this option + * enabled to remove 3DES based cipher suites. + * + * Comment this macro to keep 3DES in the default ciphersuite list. + */ +#define MBEDTLS_REMOVE_3DES_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_ECP_NO_INTERNAL_RNG + * + * When this option is disabled, mbedtls_ecp_mul() will make use of an + * internal RNG when called with a NULL \c f_rng argument, in order to protect + * against some side-channel attacks. + * + * This protection introduces a dependency of the ECP module on one of the + * DRBG or SHA modules (HMAC-DRBG, CTR-DRBG, SHA-512 or SHA-256.) For very + * constrained applications that don't require this protection (for example, + * because you're only doing signature verification, so not manipulating any + * secret, or because local/physical side-channel attacks are outside your + * threat model), it might be desirable to get rid of that dependency. + * + * \warning Enabling this option makes some uses of ECP vulnerable to some + * side-channel attacks. Only enable it if you know that's not a problem for + * your use case. + * + * Uncomment this macro to disable some counter-measures in ECP. + */ +//#define MBEDTLS_ECP_NO_INTERNAL_RNG + +/** + * \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 + * + * Enable 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 (maintenance 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_TEST_HOOKS + * + * Enable features for invasive testing such as introspection functions and + * hooks for fault injection. This enables additional unit tests. + * + * Merely enabling this feature should not change the behavior of the product. + * It only adds new code, and new branching points where the default behavior + * is the same as when this feature is disabled. + * However, this feature increases the attack surface: there is an added + * risk of vulnerabilities, and more gadgets that can make exploits easier. + * Therefore this feature must never be enabled in production. + * + * Uncomment to enable invasive tests. + */ +//#define MBEDTLS_TEST_HOOKS + +/** + * \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 applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/ssl_tls.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/ssl_tls.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \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. + * + * \note This module only achieves a 256-bit security strength if + * the generator is seeded with sufficient entropy. + * See ctr_drbg.h for more details. + * + * 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 window 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 correctly 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 correctly 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 "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 + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ \ No newline at end of file diff --git a/third-party/mbedtls-3.6/include/mbedtls/ctr_drbg.h b/third-party/mbedtls-3.6/include/mbedtls/ctr_drbg.h new file mode 100644 index 00000000..33fe63f4 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ctr_drbg.h @@ -0,0 +1,543 @@ +/** + * \file ctr_drbg.h + * + * \brief The CTR_DRBG pseudorandom generator. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 + * as the underlying block cipher, with a derivation function. + * The initial seeding grabs #MBEDTLS_CTR_DRBG_ENTROPY_LEN bytes of entropy. + * See the documentation of mbedtls_ctr_drbg_seed() for more details. + * + * Based on NIST SP 800-90A §10.2.1 table 3 and NIST SP 800-57 part 1 table 2, + * here are the security strengths achieved in typical configuration: + * - 256 bits under the default configuration of the library, + * with #MBEDTLS_CTR_DRBG_ENTROPY_LEN set to 48 or more. + * - 256 bits if #MBEDTLS_CTR_DRBG_ENTROPY_LEN is set + * to 32 or more and the DRBG is initialized with an explicit + * nonce in the \c custom parameter to mbedtls_ctr_drbg_seed(). + * - 128 bits if #MBEDTLS_CTR_DRBG_ENTROPY_LEN is + * between 24 and 47 and the DRBG is not initialized with an explicit + * nonce (see mbedtls_ctr_drbg_seed()). + * + * Note that the value of #MBEDTLS_CTR_DRBG_ENTROPY_LEN defaults to: + * - \c 48 if the module \c MBEDTLS_SHA512_C is enabled and the symbol + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is not enabled at compile time. + * This is the default configuration of the library. + * - \c 32 if the module \c MBEDTLS_SHA512_C is disabled at compile time. + * - \c 32 if \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled at compile time. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#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. + * \{ + */ + +/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN + * + * \brief The amount of entropy used per seed by default, in bytes. + */ +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +/** This is 48 bytes because the entropy module uses SHA-512 + * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is not set). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 + +#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ + +/** This is 32 bytes because the entropy module uses SHA-256 + * (the SHA512 module is disabled or + * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled). + * + * \warning To achieve a 256-bit security strength, you must pass a nonce + * to mbedtls_ctr_drbg_seed(). + */ +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */ +#endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */ + +#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 in bytes. */ +#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) + /* Invariant: the mutex is initialized if and only if f_entropy != NULL. + * This means that the mutex is initialized during the initial seeding + * in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + 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(). + * + * \note The reseed interval is + * #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default. + * You can override it by calling + * mbedtls_ctr_drbg_set_reseed_interval(). + * + * \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. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default. + * You can override it by calling mbedtls_ctr_drbg_set_entropy_len(). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note The _seed_material_ value passed to the derivation + * function in the CTR_DRBG Instantiate Process + * described in NIST SP 800-90A §10.2.1.3.2 + * is the concatenation of the string obtained from + * calling \p f_entropy and the \p custom string. + * The origin of the nonce depends on the value of + * the entropy length relative to the security strength. + * - If the entropy length is at least 1.5 times the + * security strength then the nonce is taken from the + * string obtained with \p f_entropy. + * - If the entropy length is less than the security + * strength, then the nonce is taken from \p custom. + * In this case, for compliance with SP 800-90A, + * you must pass a unique value of \p custom at + * each invocation. See SP 800-90A §8.6.7 for more + * details. + */ +#if MBEDTLS_CTR_DRBG_ENTROPY_LEN < MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2 +/** \warning When #MBEDTLS_CTR_DRBG_ENTROPY_LEN is less than + * 48, to achieve a 256-bit security strength, + * you must pass a value of \p custom that is a nonce: + * this value must never be repeated in subsequent + * runs of the same application or on a different + * device. + */ +#endif +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx The CTR_DRBG context to seed. + * It must have been initialized with + * mbedtls_ctr_drbg_init(). + * After a successful call to mbedtls_ctr_drbg_seed(), + * you may not call mbedtls_ctr_drbg_seed() again on + * the same context unless you call + * mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init() + * again first. + * After a failed call to mbedtls_ctr_drbg_seed(), + * you must call mbedtls_ctr_drbg_free(). + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a buffer size + * equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + * - #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \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 resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + * + * \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() + * or mbedtls_ctr_drbg_random(). + * 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. + * + * \note The security strength of CTR_DRBG is bounded by the + * entropy length. Thus \p len must be at least + * 32 (in bytes) to achieve a 256-bit strength. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab, in bytes. + * This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * + * The reseed interval is the number of calls to mbedtls_ctr_drbg_random() + * or mbedtls_ctr_drbg_random_with_add() after which the entropy function + * is called again. + * + * 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. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be \c NULL. + * \param len The length of the additional data. + * This must be less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \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. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional in bytes. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if + * \p add_len is more than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + * \return An error from the underlying AES cipher on failure. + */ +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \warning This function cannot report errors. You should use + * mbedtls_ctr_drbg_update_ret() instead. + * + * \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. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. This must not be + * \c NULL unless \p add_len is \c 0. + * \param add_len Length of \p additional data. This must be at + * most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT. + */ +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. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \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 in bytes. + * \param additional Additional data to update. Can be \c NULL, in which + * case the additional data is empty regardless of + * the value of \p add_len. + * \param add_len The length of the additional data + * if \p additional is not \c NULL. + * This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT + * and less than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len + * where \c entropy_len is the entropy length + * configured for the context. + * + * \return \c 0 on success. + * \return #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. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \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 in bytes. + * + * \return \c 0 on success. + * \return #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. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed + * 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. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/debug.h b/third-party/mbedtls-3.6/include/mbedtls/debug.h new file mode 100644 index 00000000..efc7e9ff --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/debug.h @@ -0,0 +1,254 @@ +/** + * \file debug.h + * + * \brief Functions for controlling and providing debug output from the library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_DEBUG_H +#define MBEDTLS_DEBUG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#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 */ + diff --git a/third-party/mbedtls-3.6/include/mbedtls/des.h b/third-party/mbedtls-3.6/include/mbedtls/des.h new file mode 100644 index 00000000..b04ad170 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/des.h @@ -0,0 +1,382 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "des_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/dhm.h b/third-party/mbedtls-3.6/include/mbedtls/dhm.h new file mode 100644 index 00000000..233b1f20 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/dhm.h @@ -0,0 +1,1086 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_DHM_H +#define MBEDTLS_DHM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif +#include "bignum.h" +#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 */ +#include "dhm_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ecdh.h b/third-party/mbedtls-3.6/include/mbedtls/ecdh.h new file mode 100644 index 00000000..e937c899 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ecdh.h @@ -0,0 +1,308 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_ECDH_H +#define MBEDTLS_ECDH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ecp.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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ecdsa.h b/third-party/mbedtls-3.6/include/mbedtls/ecdsa.h new file mode 100644 index 00000000..1a34ff27 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ecdsa.h @@ -0,0 +1,426 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ecp.h" +#include "md.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). + * + * + * \warning Since the output of the internal RNG is always the same for + * the same key and message, this limits the efficiency of + * blinding and leaks information through side channels. For + * secure behavior use mbedtls_ecdsa_sign_det_ext() instead. + * + * (Optimally the blinding is a random value that is different + * on every execution. In this case the blinding is still + * random from the attackers perspective, but is the same on + * each execution. This means that this blinding does not + * prevent attackers from recovering secrets by combining + * several measurement traces, but may prevent some attacks + * that exploit relationships between secret data.) + * + * \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 ); +/** + * \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). + * + * \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. + * + * \see ecp.h + * + * \param grp The context for the elliptic curve to use. + * This must be initialized and have group parameters + * set, for example through mbedtls_ecp_group_load(). + * \param r The MPI context in which to store the first part + * the signature. This must be initialized. + * \param s The MPI context in which to store the second part + * the signature. This must be initialized. + * \param d The private signing key. This must be initialized + * and setup, for example through mbedtls_ecp_gen_privkey(). + * \param buf The hashed content to be signed. This must be a readable + * buffer of length \p blen Bytes. It may be \c NULL if + * \p blen is zero. + * \param blen The length of \p buf in Bytes. + * \param md_alg The hash algorithm used to hash the original data. + * \param f_rng_blind The RNG function used for blinding. This must not be + * \c NULL. + * \param p_rng_blind The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context parameter. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det_ext( 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 (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ); +#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 there is a valid + * signature in sig but its 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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ecjpake.h b/third-party/mbedtls-3.6/include/mbedtls/ecjpake.h new file mode 100644 index 00000000..1e941702 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ecjpake.h @@ -0,0 +1,285 @@ +/** + * \file ecjpake.h + * + * \brief Elliptic curve J-PAKE + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#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_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ecp.h" +#include "md.h" + +#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 */ +#include "ecjpake_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ecp.h b/third-party/mbedtls-3.6/include/mbedtls/ecp.h new file mode 100644 index 00000000..6ebd2d65 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ecp.h @@ -0,0 +1,736 @@ +/** + * \file ecp.h + * + * \brief Elliptic curves over GF(p) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.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 /**< The buffer contains a valid signature followed by more data. */ +#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 \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. + * Note: unless #MBEDTLS_ECP_NO_INTERNAL_RNG is defined, when + * \p f_rng is NULL, an internal RNG (seeded from the value + * of \p m) will be used instead. + * + * \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 private key + * + * \param grp ECP group + * \param d Destination MPI (secret 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 + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \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 */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +#endif /* ecp.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ecp_internal.h b/third-party/mbedtls-3.6/include/mbedtls/ecp_internal.h new file mode 100644 index 00000000..0047bd4e --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ecp_internal.h @@ -0,0 +1,324 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [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. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(ECP_SHORTWEIERSTRASS) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * 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 in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_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 ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* ECP_MONTGOMERY */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/third-party/mbedtls-3.6/include/mbedtls/entropy.h b/third-party/mbedtls-3.6/include/mbedtls/entropy.h new file mode 100644 index 00000000..41648aaf --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/entropy.h @@ -0,0 +1,316 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "havege.h" +#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; /* 0 after init. + * 1 after the first update. + * -1 after free. */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; /* Number of entries used in source. */ + 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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/entropy_poll.h b/third-party/mbedtls-3.6/include/mbedtls/entropy_poll.h new file mode 100644 index 00000000..c348fe52 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/entropy_poll.h @@ -0,0 +1,135 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/error.h b/third-party/mbedtls-3.6/include/mbedtls/error.h new file mode 100644 index 00000000..10354543 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/error.h @@ -0,0 +1,149 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#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 + * SSL 5 1 (Started from 0x5E80) + * 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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/gcm.h b/third-party/mbedtls-3.6/include/mbedtls/gcm.h new file mode 100644 index 00000000..2a49a87f --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/gcm.h @@ -0,0 +1,320 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_GCM_H +#define MBEDTLS_GCM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.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. + * + * \warning When this function performs a decryption, it outputs the + * authentication tag and does not verify that the data is + * authentic. You should use this function to perform encryption + * only. For decryption, use mbedtls_gcm_auth_decrypt() instead. + * + * \param ctx The GCM context to use for encryption or decryption. + * \param mode The operation to perform: + * - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption. + * The ciphertext is written to \p output and the + * authentication tag is written to \p tag. + * - #MBEDTLS_GCM_DECRYPT to perform decryption. + * The plaintext is written to \p output and the + * authentication tag is written to \p tag. + * Note that this mode is not recommended, because it does + * not verify the authenticity of the data. For this reason, + * you should use mbedtls_gcm_auth_decrypt() instead of + * calling this function in decryption mode. + * \param length The length of the input data, which is equal to the length + * of the output data. + * \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. Its size is \b length. + * \param output The buffer for holding the output data. It must have room + * for \b length bytes. + * \param tag_len The length of the tag to generate. + * \param tag The buffer for holding the tag. + * + * \return \c 0 if the encryption or decryption was performed + * successfully. Note that in #MBEDTLS_GCM_DECRYPT mode, + * this does not indicate that the data is authentic. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. + * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific + * error code if the encryption or decryption failed. + */ +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 ciphertext to decrypt, which is also + * the length of the decrypted plaintext. + * \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 to verify. + * \param tag_len The length of the tag to verify. + * \param input The buffer holding the ciphertext. Its size is \b length. + * \param output The buffer for holding the decrypted plaintext. It must + * have room for \b length bytes. + * + * \return \c 0 if successful and authenticated. + * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. + * \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths are not valid. + * \return #MBEDTLS_ERR_GCM_HW_ACCEL_FAILED or a cipher-specific + * error code if the decryption failed. + */ +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 */ +#include "gcm_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/havege.h b/third-party/mbedtls-3.6/include/mbedtls/havege.h new file mode 100644 index 00000000..781a6094 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/havege.h @@ -0,0 +1,106 @@ +/** + * \file havege.h + * + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_HAVEGE_H +#define MBEDTLS_HAVEGE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/hmac_drbg.h b/third-party/mbedtls-3.6/include/mbedtls/hmac_drbg.h new file mode 100644 index 00000000..4a797d47 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/hmac_drbg.h @@ -0,0 +1,495 @@ +/** + * \file hmac_drbg.h + * + * \brief The HMAC_DRBG pseudorandom generator. + * + * This module implements the HMAC_DRBG pseudorandom generator described + * in NIST SP 800-90A: Recommendation for Random Number Generation Using + * Deterministic Random Bit Generators. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_HMAC_DRBG_H +#define MBEDTLS_HMAC_DRBG_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#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 explicitly, + * 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) + /* Invariant: the mutex is initialized if and only if + * md_ctx->md_info != NULL. This means that the mutex is initialized + * during the initial seeding in mbedtls_hmac_drbg_seed() or + * mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free(). + * + * Note that this invariant may change without notice. Do not rely on it + * and do not access the mutex directly in application code. + */ + mbedtls_threading_mutex_t mutex; +#endif +} mbedtls_hmac_drbg_context; + +/** + * \brief HMAC_DRBG context initialization. + * + * This function makes the context ready for mbedtls_hmac_drbg_seed(), + * mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free(). + * + * \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL + * by default. Override this value by calling + * mbedtls_hmac_drbg_set_reseed_interval(). + * + * \param ctx HMAC_DRBG context to be initialized. + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ); + +/** + * \brief HMAC_DRBG initial seeding. + * + * Set the initial seed and set up the entropy source for future reseeds. + * + * A typical choice for the \p f_entropy and \p p_entropy parameters is + * to use the entropy module: + * - \p f_entropy is mbedtls_entropy_func(); + * - \p p_entropy is an instance of ::mbedtls_entropy_context initialized + * with mbedtls_entropy_init() (which registers the platform's default + * entropy sources). + * + * You can provide a personalization string in addition to the + * entropy source, to make this instantiation as unique as possible. + * + * \note By default, the security strength as defined by NIST is: + * - 128 bits if \p md_info is SHA-1; + * - 192 bits if \p md_info is SHA-224; + * - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512. + * Note that SHA-256 is just as efficient as SHA-224. + * The security strength can be reduced if a smaller + * entropy length is set with + * mbedtls_hmac_drbg_set_entropy_len(). + * + * \note The default entropy length is the security strength + * (converted from bits to bytes). You can override + * it by calling mbedtls_hmac_drbg_set_entropy_len(). + * + * \note During the initial seeding, this function calls + * the entropy source to obtain a nonce + * whose length is half the entropy length. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be seeded. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + * length of the buffer. + * \p f_entropy is always called with a length that is + * less than or equal to the entropy length. + * \param p_entropy The entropy context to pass to \p f_entropy. + * \param custom The personalization string. + * This can be \c NULL, in which case the personalization + * string is empty regardless of the value of \p len. + * \param len The length of the personalization string. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2 + * where \p entropy_len is the entropy length + * described above. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if the call to \p f_entropy 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). + * + * This function is meant for use in algorithms that need a pseudorandom + * input such as deterministic ECDSA. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * after this function returns successfully, + * it is safe to call mbedtls_hmac_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param ctx HMAC_DRBG context to be initialised. + * \param md_info MD algorithm to use for HMAC_DRBG. + * \param data Concatenation of the initial entropy string and + * the additional data. + * \param data_len Length of \p data in bytes. + * + * \return \c 0 if successful. or + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is + * invalid. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough + * memory to allocate context data. + */ +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 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_hmac_drbg_random_with_add() + * or mbedtls_hmac_drbg_random(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The 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 This function sets the amount of entropy grabbed on each + * seed or reseed. + * + * See the documentation of mbedtls_hmac_drbg_seed() for the default value. + * + * \param ctx The HMAC_DRBG context. + * \param len The 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. + * + * The reseed interval is the number of calls to mbedtls_hmac_drbg_random() + * or mbedtls_hmac_drbg_random_with_add() after which the entropy function + * is called again. + * + * The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL. + * + * \param ctx The HMAC_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx, + int interval ); + +/** + * \brief This function updates the state of the HMAC_DRBG context. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional The data to update the state with. + * If this is \c NULL, there is no additional data. + * \param add_len Length of \p additional in bytes. + * Unused if \p additional is \c NULL. + * + * \return \c 0 on success, or an error from the underlying + * hash calculation. + */ +int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief HMAC_DRBG update state + * + * \warning This function cannot report errors. You should use + * mbedtls_hmac_drbg_update_ret() instead. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \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 This function reseeds the HMAC_DRBG context, that is + * extracts data from the entropy source. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param ctx The HMAC_DRBG context. + * \param additional Additional data to add to the state. + * If this is \c NULL, there is no additional data + * and \p len should be \c 0. + * \param len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT + * and also at most + * #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len + * where \p entropy_len is the entropy length + * (see mbedtls_hmac_drbg_set_entropy_len()). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy function failed. + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates an HMAC_DRBG instance with additional + * data and uses it to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + * + * \note This function is not thread-safe. It is not safe + * to call this function if another thread might be + * concurrently obtaining random numbers from the same + * context or updating or reseeding the same context. + * + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \param additional Additional data to update with. + * If this is \c NULL, there is no additional data + * and \p add_len should be \c 0. + * \param add_len The length of the additional data. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if + * \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT. + */ +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 This function uses HMAC_DRBG to generate random data. + * + * This function automatically reseeds if the reseed counter is exceeded + * or prediction resistance is enabled. + */ +#if defined(MBEDTLS_THREADING_C) +/** + * \note When Mbed TLS is built with threading support, + * it is safe to call mbedtls_ctr_drbg_random() + * from multiple threads. Other operations, including + * reseeding, are not thread-safe. + */ +#endif /* MBEDTLS_THREADING_C */ +/** + * \param p_rng The HMAC_DRBG context. This must be a pointer to a + * #mbedtls_hmac_drbg_context structure. + * \param output The buffer to fill. + * \param out_len The length of the buffer in bytes. + * This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED + * if a call to the entropy source failed. + * \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if + * \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST. + */ +int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len ); + +/** + * \brief This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + * + * \param ctx The HMAC_DRBG context to free. + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed + * failure. + */ +int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_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 HMAC_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on + * reseed failure. + * \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing + * seed file is too large. + */ +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 The HMAC_DRBG Checkup routine. + * + * \return \c 0 if successful. + * \return \c 1 if the test failed. + */ +int mbedtls_hmac_drbg_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* hmac_drbg.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/md.h b/third-party/mbedtls-3.6/include/mbedtls/md.h new file mode 100644 index 00000000..2903e435 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/md.h @@ -0,0 +1,480 @@ + /** + * \file md.h + * + * \brief The generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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. + * + * \note The list starts with the strongest available hashes. + * + * \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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/md2.h b/third-party/mbedtls-3.6/include/mbedtls/md2.h new file mode 100644 index 00000000..795db37d --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/md2.h @@ -0,0 +1,334 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_MD2_H +#define MBEDTLS_MD2_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "md2_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/md4.h b/third-party/mbedtls-3.6/include/mbedtls/md4.h new file mode 100644 index 00000000..e091fd91 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/md4.h @@ -0,0 +1,339 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ +#ifndef MBEDTLS_MD4_H +#define MBEDTLS_MD4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "md4_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/md5.h b/third-party/mbedtls-3.6/include/mbedtls/md5.h new file mode 100644 index 00000000..e24c87de --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/md5.h @@ -0,0 +1,339 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "md5_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/md_internal.h b/third-party/mbedtls-3.6/include/mbedtls/md_internal.h new file mode 100644 index 00000000..847f50aa --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/md_internal.h @@ -0,0 +1,140 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/memory_buffer_alloc.h b/third-party/mbedtls-3.6/include/mbedtls/memory_buffer_alloc.h new file mode 100644 index 00000000..89c06174 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/memory_buffer_alloc.h @@ -0,0 +1,176 @@ +/** + * \file memory_buffer_alloc.h + * + * \brief Buffer-based memory allocator + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H +#define MBEDTLS_MEMORY_BUFFER_ALLOC_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/net.h b/third-party/mbedtls-3.6/include/mbedtls/net.h new file mode 100644 index 00000000..6c7a49d3 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/net.h @@ -0,0 +1,62 @@ +/** + * \file net.h + * + * \brief Deprecated header file that includes net_sockets.h + * + * \deprecated Superseded by mbedtls/net_sockets.h + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#include "net_sockets.h" +#if defined(MBEDTLS_DEPRECATED_WARNING) +#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h" +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/net_sockets.h b/third-party/mbedtls-3.6/include/mbedtls/net_sockets.h new file mode 100644 index 00000000..e58b0681 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/net_sockets.h @@ -0,0 +1,264 @@ +/** + * \file net_sockets.h + * + * \brief Network communication functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_NET_SOCKETS_H +#define MBEDTLS_NET_SOCKETS_H + +#if defined(MBEDTLS_NET_C) + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#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_UNKNOWN_HOST, + * 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, can be NULL + * \param buf_size Size of the client_ip buffer + * \param ip_len Will receive the size of the client IP written, + * can be NULL if client_ip is null + * + * \return 0 if successful, or + * MBEDTLS_ERR_NET_SOCKET_FAILED, + * MBEDTLS_ERR_NET_BIND_FAILED, + * 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. + * + * \note The current implementation of this function uses + * select() and returns an error if the file descriptor + * is \c FD_SETSIZE or greater. + * + * \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 if successful. + * MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out. + * MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal. + * Another negative error code (MBEDTLS_ERR_NET_xxx) + * for other failures. + * + * \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 + +#endif /* MBEDTLS_NET_SOCKETS_H */ \ No newline at end of file diff --git a/third-party/mbedtls-3.6/include/mbedtls/oid.h b/third-party/mbedtls-3.6/include/mbedtls/oid.h new file mode 100644 index 00000000..40b4bc4f --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/oid.h @@ -0,0 +1,614 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "md.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "x509.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/padlock.h b/third-party/mbedtls-3.6/include/mbedtls/padlock.h new file mode 100644 index 00000000..91ad2a6c --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/padlock.h @@ -0,0 +1,139 @@ +/** + * \file padlock.h + * + * \brief VIA PadLock ACE for HW encryption/decryption supported by some + * processors + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PADLOCK_H +#define MBEDTLS_PADLOCK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "aes.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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/pem.h b/third-party/mbedtls-3.6/include/mbedtls/pem.h new file mode 100644 index 00000000..dfcc5187 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/pem.h @@ -0,0 +1,161 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/pk.h b/third-party/mbedtls-3.6/include/mbedtls/pk.h new file mode 100644 index 00000000..c636c3d5 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/pk.h @@ -0,0 +1,647 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "ecdsa.h" +#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 buffer contains a valid signature followed by more data. */ +#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 there is a valid + * signature in sig but its length is less than \p siglen, + * 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 there is a valid + * signature in sig but its length is less than \p siglen, + * 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. + * + * \note In order to ensure enough space for the signature, the + * \p sig buffer size must be of at least + * `max(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE)` bytes. + */ +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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/pk_internal.h b/third-party/mbedtls-3.6/include/mbedtls/pk_internal.h new file mode 100644 index 00000000..038acf9a --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/pk_internal.h @@ -0,0 +1,140 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" + +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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/pkcs11.h b/third-party/mbedtls-3.6/include/mbedtls/pkcs11.h new file mode 100644 index 00000000..c620722e --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/pkcs11.h @@ -0,0 +1,199 @@ +/** + * \file pkcs11.h + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PKCS11_H +#define MBEDTLS_PKCS11_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS11_C) + +#include "x509_crt.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/pkcs12.h b/third-party/mbedtls-3.6/include/mbedtls/pkcs12.h new file mode 100644 index 00000000..9cbcb173 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/pkcs12.h @@ -0,0 +1,155 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" +#include "cipher.h" +#include "asn1.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 + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \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 ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/pkcs5.h b/third-party/mbedtls-3.6/include/mbedtls/pkcs5.h new file mode 100644 index 00000000..759d1722 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/pkcs5.h @@ -0,0 +1,130 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "md.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 + +#if defined(MBEDTLS_ASN1_PARSE_C) + +/** + * \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 ); + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +/** + * \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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/platform.h b/third-party/mbedtls-3.6/include/mbedtls/platform.h new file mode 100644 index 00000000..4eaad53c --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/platform.h @@ -0,0 +1,373 @@ +/** + * \file platform.h + * + * \brief The Mbed TLS platform abstraction layer. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "platform_time.h" +#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 MBEDTLS_PLATFORM_STD_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 +#include "platform_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/platform_time.h b/third-party/mbedtls-3.6/include/mbedtls/platform_time.h new file mode 100644 index 00000000..e132f6a6 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/platform_time.h @@ -0,0 +1,107 @@ +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ripemd160.h b/third-party/mbedtls-3.6/include/mbedtls/ripemd160.h new file mode 100644 index 00000000..e954c65b --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ripemd160.h @@ -0,0 +1,264 @@ +/** + * \file ripemd160.h + * + * \brief RIPE MD-160 message digest + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_RIPEMD160_H +#define MBEDTLS_RIPEMD160_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "ripemd160_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/rsa.h b/third-party/mbedtls-3.6/include/mbedtls/rsa.h new file mode 100644 index 00000000..cfb66dd8 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/rsa.h @@ -0,0 +1,1170 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#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; /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + 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) + /* Invariant: the mutex is initialized iff ver != 0. */ + 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 overridden 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 overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + */ +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. + * A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \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. + * A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe. + */ +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. + * A buffer length of #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \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 */ +#include "rsa_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/rsa_internal.h b/third-party/mbedtls-3.6/include/mbedtls/rsa_internal.h new file mode 100644 index 00000000..953cb7b8 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/rsa_internal.h @@ -0,0 +1,251 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * 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. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/sha1.h b/third-party/mbedtls-3.6/include/mbedtls/sha1.h new file mode 100644 index 00000000..4ae8ad60 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/sha1.h @@ -0,0 +1,347 @@ +/** + * \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 The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "sha1_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/sha256.h b/third-party/mbedtls-3.6/include/mbedtls/sha256.h new file mode 100644 index 00000000..9bcf28cb --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/sha256.h @@ -0,0 +1,303 @@ +/** + * \file sha256.h + * + * \brief The SHA-224 and SHA-256 cryptographic hash function. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "sha256_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/sha512.h b/third-party/mbedtls-3.6/include/mbedtls/sha512.h new file mode 100644 index 00000000..b7f41ea3 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/sha512.h @@ -0,0 +1,305 @@ +/** + * \file sha512.h + * + * \brief The SHA-384 and SHA-512 cryptographic hash function. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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. + * + * \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. + * This function is for internal use only. + * + * \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 */ +#include "sha512_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ssl.h b/third-party/mbedtls-3.6/include/mbedtls/ssl.h new file mode 100644 index 00000000..0f4cbb62 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ssl.h @@ -0,0 +1,2697 @@ +/** + * \file ssl.h + * + * \brief SSL/TLS functions. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_H +#define MBEDTLS_SSL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "ecp.h" + +#include "ssl_ciphersuites.h" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "x509_crt.h" +#include "x509_crl.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "dhm.h" +#endif + +#if defined(MBEDTLS_ECDH_C) +#include "ecdh.h" +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) +#include "zlib.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "platform_time.h" +#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 */ +#define MBEDTLS_ERR_SSL_BAD_CONFIG -0x5E80 /**< Invalid value in SSL config */ + +/* + * 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 */ +#define MBEDTLS_SSL_MAX_ALPN_NAME_LEN 255 /*!< Maximum size in bytes of a protocol name in alpn ext., RFC 7301 */ + +#define MBEDTLS_SSL_MAX_ALPN_LIST_LEN 65535 /*!< Maximum size in bytes of list in alpn ext., RFC 7301 */ + +/* 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 +}; + +#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 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_send_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 + * + * \note See \c mbedtls_x509_crt_verify() for notes regarding the + * parameters ca_chain (maps to trust_ca for that function) + * and ca_crl. + * + * \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 multiple 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. + * + * \note The provided \p pk_key needs to match the public key in the + * first certificate in \p own_cert, or all handshakes using + * that certificate will fail. It is your responsibility + * to ensure that; this function will not perform any check. + * You may use mbedtls_pk_check_pair() in order to perform + * this check yourself, but be aware that this function can + * be computationally expensive on some key types. + * + * \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. + * (Typical: #MBEDTLS_SSL_MAX_CONTENT_LEN, by default that is + * set to `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) + * (Default: #MBEDTLS_SSL_MAX_FRAG_LEN_NONE) + * + * \note With TLS, this currently only affects ApplicationData (sent + * with \c mbedtls_ssl_read()), not handshake messages. + * With DTLS, this affects both ApplicationData and handshake. + * + * \note On the client side, the maximum fragment length extension + * *will not* be used, unless the maximum fragment length has + * been set via this function to a value different than + * #MBEDTLS_SSL_MAX_FRAG_LEN_NONE. + * + * \note This sets the maximum length for a record's payload, + * excluding record overhead that will be added to it, see + * \c mbedtls_ssl_get_record_expansion(). + * + * \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 The SSL context to use. + * + * \return \c 0 if the certificate verification was successful. + * \return \c -1u if the result is not available. This may happen + * e.g. if the handshake aborts early, or a verification + * callback returned a fatal error. + * \return A bitwise combination of \c MBEDTLS_X509_BADCERT_XXX + * and \c MBEDTLS_X509_BADCRL_XXX failure 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. + * + * + * \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. + * + * \note Only the server certificate is copied, and not the full chain, + * so you should not attempt to validate the certificate again + * by calling \c mbedtls_x509_crt_verify() on it. + * Instead, you should use the results from the verification + * in the original handshake by calling \c mbedtls_ssl_get_verify_result() + * after loading the session again into a new SSL context + * using \c mbedtls_ssl_set_session(). + * + * \note Once the session object is not needed anymore, you should + * free it by calling \c mbedtls_ssl_session_free(). + * + * \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 0, a positive + * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop + * using the SSL context for reading or writing, and 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 value greater that or equal to 0. When + * the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be + * some partial data in the output buffer, however this is not + * yet sent. + * + * \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. + * + * \note Attempting to write 0 bytes will result in an empty TLS + * application record being sent. + */ +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 relevant 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 + * + * \note A session object can be freed even if the SSL context + * that was used to retrieve the session is still in use. + * + * \param session SSL session + */ +void mbedtls_ssl_session_free( mbedtls_ssl_session *session ); + +#ifdef __cplusplus +} +#endif + +#endif /* ssl.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ssl_cache.h b/third-party/mbedtls-3.6/include/mbedtls/ssl_cache.h new file mode 100644 index 00000000..612d8177 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ssl_cache.h @@ -0,0 +1,175 @@ +/** + * \file ssl_cache.h + * + * \brief SSL session cache implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_CACHE_H +#define MBEDTLS_SSL_CACHE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ssl_ciphersuites.h b/third-party/mbedtls-3.6/include/mbedtls/ssl_ciphersuites.h new file mode 100644 index 00000000..fcfbca83 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ssl_ciphersuites.h @@ -0,0 +1,517 @@ +/** + * \file ssl_ciphersuites.h + * + * \brief SSL Ciphersuites for mbed TLS + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_CIPHERSUITES_H +#define MBEDTLS_SSL_CIPHERSUITES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" +#include "cipher.h" +#include "md.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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ssl_cookie.h b/third-party/mbedtls-3.6/include/mbedtls/ssl_cookie.h new file mode 100644 index 00000000..cd526f6d --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ssl_cookie.h @@ -0,0 +1,140 @@ +/** + * \file ssl_cookie.h + * + * \brief DTLS cookie callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_COOKIE_H +#define MBEDTLS_SSL_COOKIE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ssl_internal.h b/third-party/mbedtls-3.6/include/mbedtls/ssl_internal.h new file mode 100644 index 00000000..6a04c8d0 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ssl_internal.h @@ -0,0 +1,821 @@ +/** + * \file ssl_internal.h + * + * \brief Internal functions shared by the SSL modules + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_INTERNAL_H +#define MBEDTLS_SSL_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "ssl.h" +#include "cipher.h" + +#if defined(MBEDTLS_MD5_C) +#include "md5.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "sha512.h" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#include "ecjpake.h" +#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 + +/* This macro determines whether CBC is supported. */ +#if defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_AES_C) || \ + defined(MBEDTLS_CAMELLIA_C) || \ + defined(MBEDTLS_DES_C) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_CBC +#endif + +/* This macro determines whether the CBC construct used in TLS 1.0-1.2 (as + * opposed to the very different CBC construct used in SSLv3) is supported. */ +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) && \ + ( defined(MBEDTLS_SSL_PROTO_TLS1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) || \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) ) +#define MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC +#endif + +/* + * 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 \ + ) + +/* Maximum size in bytes of list in sig-hash algorithm ext., RFC 5246 */ +#define MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN 65534 + +/* Maximum size in bytes of list in supported elliptic curve ext., RFC 4492 */ +#define MBEDTLS_SSL_MAX_CURVE_LIST_LEN 65535 + +/* + * 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) + +/** + * \brief This function checks if the remaining size in a buffer is + * greater or equal than a needed space. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + * \return Zero if the needed space is available in the buffer, non-zero + * otherwise. + */ +static inline int mbedtls_ssl_chk_buf_ptr( const uint8_t *cur, + const uint8_t *end, size_t need ) +{ + return( ( cur > end ) || ( need > (size_t)( end - cur ) ) ); +} + +/** + * \brief This macro checks if the remaining size in a buffer is + * greater or equal than a needed space. If it is not the case, + * it returns an SSL_BUFFER_TOO_SMALL error. + * + * \param cur Pointer to the current position in the buffer. + * \param end Pointer to one past the end of the buffer. + * \param need Needed space in bytes. + * + */ +#define MBEDTLS_SSL_CHK_BUF_PTR( cur, end, need ) \ + do { \ + if( mbedtls_ssl_chk_buf_ptr( ( cur ), ( end ), ( need ) ) != 0 ) \ + { \ + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); \ + } \ + } while( 0 ) + +#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++ ) + { + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } + + 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 */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/** \brief Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The additional data prepended to \p data. This + * must point to a readable buffer of \p add_data_len + * bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The data appended to \p add_data. This must point + * to a readable buffer of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of \p data in bytes. + * \param max_data_len The maximal length of \p data in bytes. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 + * Success. + * \retval non-zero + * Failure. + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ); + +/** \brief Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * + * \param dst The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src_base The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. + * \param offset_secret The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset_secret. + * \param offset_max The maximal value of \p offset_secret. + * \param len The number of bytes to copy. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ); +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#ifdef __cplusplus +} +#endif + +#endif /* ssl_internal.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/ssl_ticket.h b/third-party/mbedtls-3.6/include/mbedtls/ssl_ticket.h new file mode 100644 index 00000000..53c39c5f --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/ssl_ticket.h @@ -0,0 +1,167 @@ +/** + * \file ssl_ticket.h + * + * \brief TLS server ticket callbacks implementation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_SSL_TICKET_H +#define MBEDTLS_SSL_TICKET_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* + * 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. + */ + +#include "ssl.h" +#include "cipher.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#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 mbedtls_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 mbedtls_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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/threading.h b/third-party/mbedtls-3.6/include/mbedtls/threading.h new file mode 100644 index 00000000..f1d53bdb --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/threading.h @@ -0,0 +1,139 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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; + /* is_valid is 0 after a failed init or a free, and nonzero after a + * successful init. This field is not considered part of the public + * API of Mbed TLS and may change without notice. */ + 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 */ +#include "threading_alt.h" + +/** + * \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 + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex; +#endif +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/timing.h b/third-party/mbedtls-3.6/include/mbedtls/timing.h new file mode 100644 index 00000000..564e76b8 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/timing.h @@ -0,0 +1,186 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "timing_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/version.h b/third-party/mbedtls-3.6/include/mbedtls/version.h new file mode 100644 index 00000000..622bebf5 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/version.h @@ -0,0 +1,137 @@ +/** + * \file version.h + * + * \brief Run-time version information + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 2 +#define MBEDTLS_VERSION_MINOR 7 +#define MBEDTLS_VERSION_PATCH 19 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x02071300 +#define MBEDTLS_VERSION_STRING "2.7.19" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 2.7.19" + +#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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/x509.h b/third-party/mbedtls-3.6/include/mbedtls/x509.h new file mode 100644 index 00000000..e8b98a1e --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/x509.h @@ -0,0 +1,358 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#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 occurred, 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 occurred, + * 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 occurred, + * 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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/x509_crl.h b/third-party/mbedtls-3.6/include/mbedtls/x509_crl.h new file mode 100644 index 00000000..2ade47c8 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/x509_crl.h @@ -0,0 +1,199 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#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 Multiple 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 Multiple 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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/x509_crt.h b/third-party/mbedtls-3.6/include/mbedtls/x509_crt.h new file mode 100644 index 00000000..af2a3b42 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/x509_crt.h @@ -0,0 +1,710 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" +#include "x509_crl.h" + +/** + * \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 DER-encoded or one or more concatenated PEM-encoded + * certificates and add them to the chained list. + * + * For CRTs in PEM encoding, the function parses permissively: + * if at least one certificate can be parsed, the function + * returns the number of certificates for which parsing failed + * (hence \c 0 if all certificates were parsed successfully). + * If no certificate could be parsed, the function returns + * the first (negative) error encountered during parsing. + * + * PEM encoded certificates may be interleaved by other data + * such as human readable descriptions of their content, as + * long as the certificates are enclosed in the PEM specific + * '-----{BEGIN/END} CERTIFICATE-----' delimiters. + * + * \param chain The chain to which to add the parsed certificates. + * \param buf The buffer holding the certificate data in PEM or DER format. + * For certificates in PEM encoding, this may be a concatenation + * of multiple certificates; for DER encoding, the buffer must + * comprise exactly one certificate. + * \param buflen The size of \p buf, including the terminating \c NULL byte + * in case of PEM encoded data. + * + * \return \c 0 if all certificates were parsed successfully. + * \return The (positive) number of certificates that couldn't + * be parsed if parsing was partly successful (see above). + * \return A negative X509 or PEM error code otherwise. + * + */ +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. + * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs (see note above) + * \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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/x509_csr.h b/third-party/mbedtls-3.6/include/mbedtls/x509_csr.h new file mode 100644 index 00000000..5dfb4213 --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/x509_csr.h @@ -0,0 +1,332 @@ +/** + * \file x509_csr.h + * + * \brief X.509 certificate signing request parsing and writing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_X509_CSR_H +#define MBEDTLS_X509_CSR_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#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 + * + * \note The decipherOnly flag from the Key Usage + * extension is represented by bit 8 (i.e. + * 0x8000), which cannot typically be represented + * in an unsigned char. Therefore, the flag + * decipherOnly (i.e. + * #MBEDTLS_X509_KU_DECIPHER_ONLY) cannot be set using this + * function. + */ +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 */ diff --git a/third-party/mbedtls-3.6/include/mbedtls/xtea.h b/third-party/mbedtls-3.6/include/mbedtls/xtea.h new file mode 100644 index 00000000..c0259b8c --- /dev/null +++ b/third-party/mbedtls-3.6/include/mbedtls/xtea.h @@ -0,0 +1,166 @@ +/** + * \file xtea.h + * + * \brief XTEA block cipher (32-bit) + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +#ifndef MBEDTLS_XTEA_H +#define MBEDTLS_XTEA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 */ +#include "xtea_alt.h" +#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 */ diff --git a/third-party/mbedtls-3.6/library/.gitignore b/third-party/mbedtls-3.6/library/.gitignore new file mode 100644 index 00000000..3a63a63a --- /dev/null +++ b/third-party/mbedtls-3.6/library/.gitignore @@ -0,0 +1,4 @@ +*.o +libmbed* +*.sln +*.vcxproj diff --git a/third-party/mbedtls-3.6/library/CMakeLists.txt b/third-party/mbedtls-3.6/library/CMakeLists.txt new file mode 100644 index 00000000..3c105ddc --- /dev/null +++ b/third-party/mbedtls-3.6/library/CMakeLists.txt @@ -0,0 +1,169 @@ +option(USE_STATIC_MBEDTLS_LIBRARY "Build mbed TLS static library." ON) +option(USE_SHARED_MBEDTLS_LIBRARY "Build mbed TLS shared library." OFF) +option(LINK_WITH_PTHREAD "Explicitly link mbed TLS library to pthread." OFF) + +set(src_crypto + aes.c + aesni.c + arc4.c + asn1parse.c + asn1write.c + base64.c + bignum.c + blowfish.c + camellia.c + ccm.c + cipher.c + cipher_wrap.c + cmac.c + ctr_drbg.c + des.c + dhm.c + ecdh.c + ecdsa.c + ecjpake.c + ecp.c + ecp_curves.c + entropy.c + entropy_poll.c + error.c + gcm.c + havege.c + hmac_drbg.c + md.c + md2.c + md4.c + md5.c + md_wrap.c + memory_buffer_alloc.c + oid.c + padlock.c + pem.c + pk.c + pk_wrap.c + pkcs12.c + pkcs5.c + pkparse.c + pkwrite.c + platform.c + ripemd160.c + rsa.c + rsa_internal.c + sha1.c + sha256.c + sha512.c + threading.c + timing.c + version.c + version_features.c + xtea.c +) + +set(src_x509 + certs.c + pkcs11.c + x509.c + x509_create.c + x509_crl.c + x509_crt.c + x509_csr.c + x509write_crt.c + x509write_csr.c +) + +set(src_tls + debug.c + net_sockets.c + ssl_cache.c + ssl_ciphersuites.c + ssl_cli.c + ssl_cookie.c + ssl_srv.c + ssl_ticket.c + ssl_tls.c +) + +if(CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes") +endif(CMAKE_COMPILER_IS_GNUCC) + +if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wmissing-prototypes -Wdocumentation -Wno-documentation-deprecated-sync -Wunreachable-code") +endif(CMAKE_COMPILER_IS_CLANG) + +if(UNSAFE_BUILD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-error") + set(CMAKE_C_FLAGS_ASAN "${CMAKE_C_FLAGS_ASAN} -Wno-error") + set(CMAKE_C_FLAGS_ASANDBG "${CMAKE_C_FLAGS_ASANDBG} -Wno-error") +endif(UNSAFE_BUILD) + +if(WIN32) + set(libs ${libs} ws2_32) +endif(WIN32) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +if(LINK_WITH_PTHREAD) + set(libs ${libs} pthread) +endif() + +if (NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + message(FATAL_ERROR "Need to choose static or shared mbedtls build!") +endif(NOT USE_STATIC_MBEDTLS_LIBRARY AND NOT USE_SHARED_MBEDTLS_LIBRARY) + +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + set(mbedtls_static_target "mbedtls_static") + set(mbedx509_static_target "mbedx509_static") + set(mbedcrypto_static_target "mbedcrypto_static") +elseif(USE_STATIC_MBEDTLS_LIBRARY) + set(mbedtls_static_target "mbedtls") + set(mbedx509_static_target "mbedx509") + set(mbedcrypto_static_target "mbedcrypto") +endif() + +if(USE_STATIC_MBEDTLS_LIBRARY) + add_library(${mbedcrypto_static_target} STATIC ${src_crypto}) + set_target_properties(${mbedcrypto_static_target} PROPERTIES OUTPUT_NAME mbedcrypto) + target_link_libraries(${mbedcrypto_static_target} ${libs}) + + add_library(${mbedx509_static_target} STATIC ${src_x509}) + set_target_properties(${mbedx509_static_target} PROPERTIES OUTPUT_NAME mbedx509) + target_link_libraries(${mbedx509_static_target} ${libs} ${mbedcrypto_static_target}) + + add_library(${mbedtls_static_target} STATIC ${src_tls}) + set_target_properties(${mbedtls_static_target} PROPERTIES OUTPUT_NAME mbedtls) + target_link_libraries(${mbedtls_static_target} ${libs} ${mbedx509_static_target}) + + install(TARGETS ${mbedtls_static_target} ${mbedx509_static_target} ${mbedcrypto_static_target} + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif(USE_STATIC_MBEDTLS_LIBRARY) + +if(USE_SHARED_MBEDTLS_LIBRARY) + add_library(mbedcrypto SHARED ${src_crypto}) + set_target_properties(mbedcrypto PROPERTIES VERSION 2.7.19 SOVERSION 2) + target_link_libraries(mbedcrypto ${libs}) + + add_library(mbedx509 SHARED ${src_x509}) + set_target_properties(mbedx509 PROPERTIES VERSION 2.7.19 SOVERSION 0) + target_link_libraries(mbedx509 ${libs} mbedcrypto) + + add_library(mbedtls SHARED ${src_tls}) + set_target_properties(mbedtls PROPERTIES VERSION 2.7.19 SOVERSION 10) + target_link_libraries(mbedtls ${libs} mbedx509) + + install(TARGETS mbedtls mbedx509 mbedcrypto + DESTINATION ${LIB_INSTALL_DIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +endif(USE_SHARED_MBEDTLS_LIBRARY) + +add_custom_target(lib DEPENDS mbedcrypto mbedx509 mbedtls) +if(USE_STATIC_MBEDTLS_LIBRARY AND USE_SHARED_MBEDTLS_LIBRARY) + add_dependencies(lib mbedcrypto_static mbedx509_static mbedtls_static) +endif() diff --git a/third-party/mbedtls-3.6/library/Makefile b/third-party/mbedtls-3.6/library/Makefile new file mode 100644 index 00000000..51d72595 --- /dev/null +++ b/third-party/mbedtls-3.6/library/Makefile @@ -0,0 +1,172 @@ + +# Also see "include/mbedtls/config.h" + +CFLAGS ?= -O2 +WARNING_CFLAGS ?= -Wall -W -Wdeclaration-after-statement +LDFLAGS ?= + +LOCAL_CFLAGS = $(WARNING_CFLAGS) -I../include -D_FILE_OFFSET_BITS=64 +LOCAL_LDFLAGS = + +ifdef DEBUG +LOCAL_CFLAGS += -g3 +endif + +# MicroBlaze specific options: +# CFLAGS += -mno-xl-soft-mul -mxl-barrel-shift + +# To compile on Plan9: +# CFLAGS += -D_BSD_EXTENSION + +# if were running on Windows build for Windows +ifdef WINDOWS +WINDOWS_BUILD=1 +endif + +# To compile as a shared library: +ifdef SHARED +# all code is position-indep with mingw, avoid warning about useless flag +ifndef WINDOWS_BUILD +LOCAL_CFLAGS += -fPIC -fpic +endif +endif + +SOEXT_TLS=so.10 +SOEXT_X509=so.0 +SOEXT_CRYPTO=so.2 + +# Set DLEXT=dylib to compile as a shared library for Mac OS X +DLEXT ?= so + +# Set AR_DASH= (empty string) to use an ar implementation that does not accept +# the - prefix for command line options (e.g. llvm-ar) +AR_DASH ?= - + +# Windows shared library extension: +ifdef WINDOWS_BUILD +DLEXT=dll +endif + +OBJS_CRYPTO= aes.o aesni.o arc4.o \ + asn1parse.o asn1write.o base64.o \ + bignum.o blowfish.o camellia.o \ + ccm.o cipher.o cipher_wrap.o \ + cmac.o ctr_drbg.o des.o \ + dhm.o ecdh.o ecdsa.o \ + ecjpake.o ecp.o \ + ecp_curves.o entropy.o entropy_poll.o \ + error.o gcm.o havege.o \ + hmac_drbg.o md.o md2.o \ + md4.o md5.o md_wrap.o \ + memory_buffer_alloc.o oid.o \ + padlock.o pem.o pk.o \ + pk_wrap.o pkcs12.o pkcs5.o \ + pkparse.o pkwrite.o platform.o \ + ripemd160.o rsa_internal.o rsa.o \ + sha1.o sha256.o sha512.o \ + threading.o timing.o version.o \ + version_features.o xtea.o + +OBJS_X509= certs.o pkcs11.o x509.o \ + x509_create.o x509_crl.o x509_crt.o \ + x509_csr.o x509write_crt.o x509write_csr.o + +OBJS_TLS= debug.o net_sockets.o \ + ssl_cache.o ssl_ciphersuites.o \ + ssl_cli.o ssl_cookie.o \ + ssl_srv.o ssl_ticket.o \ + ssl_tls.o + +.SILENT: + +.PHONY: all static shared clean + +ifndef SHARED +all: static +else +all: shared static +endif + +static: libmbedcrypto.a libmbedx509.a libmbedtls.a + +shared: libmbedcrypto.$(DLEXT) libmbedx509.$(DLEXT) libmbedtls.$(DLEXT) + +# tls +libmbedtls.a: $(OBJS_TLS) + echo " AR $@" + $(AR) $(AR_DASH)rc $@ $(OBJS_TLS) + echo " RL $@" + $(AR) $(AR_DASH)s $@ + +libmbedtls.$(SOEXT_TLS): $(OBJS_TLS) libmbedx509.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.so: libmbedtls.$(SOEXT_TLS) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedtls.dylib: $(OBJS_TLS) libmbedx509.dylib + echo " LD $@" + $(CC) -dynamiclib -L. -lmbedcrypto -lmbedx509 $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_TLS) + +libmbedtls.dll: $(OBJS_TLS) libmbedx509.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_TLS) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -lmbedx509 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# x509 +libmbedx509.a: $(OBJS_X509) + echo " AR $@" + $(AR) $(AR_DASH)rc $@ $(OBJS_X509) + echo " RL $@" + $(AR) $(AR_DASH)s $@ + +libmbedx509.$(SOEXT_X509): $(OBJS_X509) libmbedcrypto.so + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.so: libmbedx509.$(SOEXT_X509) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedx509.dylib: $(OBJS_X509) libmbedcrypto.dylib + echo " LD $@" + $(CC) -dynamiclib -L. -lmbedcrypto $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_X509) + +libmbedx509.dll: $(OBJS_X509) libmbedcrypto.dll + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_X509) -lws2_32 -lwinmm -lgdi32 -L. -lmbedcrypto -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +# crypto +libmbedcrypto.a: $(OBJS_CRYPTO) + echo " AR $@" + $(AR) $(AR_DASH)rc $@ $(OBJS_CRYPTO) + echo " RL $@" + $(AR) $(AR_DASH)s $@ + +libmbedcrypto.$(SOEXT_CRYPTO): $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.so: libmbedcrypto.$(SOEXT_CRYPTO) + echo " LN $@ -> $<" + ln -sf $< $@ + +libmbedcrypto.dylib: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -dynamiclib $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ $(OBJS_CRYPTO) + +libmbedcrypto.dll: $(OBJS_CRYPTO) + echo " LD $@" + $(CC) -shared -Wl,-soname,$@ -Wl,--out-implib,$@.a -o $@ $(OBJS_CRYPTO) -lws2_32 -lwinmm -lgdi32 -static-libgcc $(LOCAL_LDFLAGS) $(LDFLAGS) + +.c.o: + echo " CC $<" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) -c $< + +clean: +ifndef WINDOWS + rm -f *.o libmbed* +else + del /Q /F *.o libmbed* +endif diff --git a/third-party/mbedtls-3.6/library/aes.c b/third-party/mbedtls-3.6/library/aes.c new file mode 100644 index 00000000..b8aee907 --- /dev/null +++ b/third-party/mbedtls-3.6/library/aes.c @@ -0,0 +1,1565 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + GET_UINT32_LE( t.X[0], input, 0 ); t.X[0] ^= *RK++; + GET_UINT32_LE( t.X[1], input, 4 ); t.X[1] ^= *RK++; + GET_UINT32_LE( t.X[2], input, 8 ); t.X[2] ^= *RK++; + GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_FROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_FROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[0] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[1] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[2] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) FSb[ ( t.Y[3] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( t.Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( t.X[0], output, 0 ); + PUT_UINT32_LE( t.X[1], output, 4 ); + PUT_UINT32_LE( t.X[2], output, 8 ); + PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_zeroize( &t, sizeof( t ) ); + + 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 = ctx->rk; + struct + { + uint32_t X[4]; + uint32_t Y[4]; + } t; + + GET_UINT32_LE( t.X[0], input, 0 ); t.X[0] ^= *RK++; + GET_UINT32_LE( t.X[1], input, 4 ); t.X[1] ^= *RK++; + GET_UINT32_LE( t.X[2], input, 8 ); t.X[2] ^= *RK++; + GET_UINT32_LE( t.X[3], input, 12 ); t.X[3] ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + AES_RROUND( t.X[0], t.X[1], t.X[2], t.X[3], t.Y[0], t.Y[1], t.Y[2], t.Y[3] ); + } + + AES_RROUND( t.Y[0], t.Y[1], t.Y[2], t.Y[3], t.X[0], t.X[1], t.X[2], t.X[3] ); + + t.X[0] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[0] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 24 ) & 0xFF ] << 24 ); + + t.X[1] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[1] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 24 ) & 0xFF ] << 24 ); + + t.X[2] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[2] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[3] >> 24 ) & 0xFF ] << 24 ); + + t.X[3] = *RK++ ^ \ + ( (uint32_t) RSb[ ( t.Y[3] ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( t.Y[2] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( t.Y[1] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( t.Y[0] >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( t.X[0], output, 0 ); + PUT_UINT32_LE( t.X[1], output, 4 ); + PUT_UINT32_LE( t.X[2], output, 8 ); + PUT_UINT32_LE( t.X[3], output, 12 ); + + mbedtls_zeroize( &t, sizeof( t ) ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/aesni.c b/third-party/mbedtls-3.6/library/aesni.c new file mode 100644 index 00000000..d4969f52 --- /dev/null +++ b/third-party/mbedtls-3.6/library/aesni.c @@ -0,0 +1,489 @@ +/* + * AES-NI support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * [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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AESNI_C) + +#include "mbedtls/aesni.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/library/arc4.c b/third-party/mbedtls-3.6/library/arc4.c new file mode 100644 index 00000000..338ecd7a --- /dev/null +++ b/third-party/mbedtls-3.6/library/arc4.c @@ -0,0 +1,230 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARC4_C) + +#include "mbedtls/arc4.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +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 */ diff --git a/third-party/mbedtls-3.6/library/asn1parse.c b/third-party/mbedtls-3.6/library/asn1parse.c new file mode 100644 index 00000000..9b445585 --- /dev/null +++ b/third-party/mbedtls-3.6/library/asn1parse.c @@ -0,0 +1,418 @@ +/* + * Generic ASN.1 parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* 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; +} + +/* + * 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 */ diff --git a/third-party/mbedtls-3.6/library/asn1write.c b/third-party/mbedtls-3.6/library/asn1write.c new file mode 100644 index 00000000..9740320b --- /dev/null +++ b/third-party/mbedtls-3.6/library/asn1write.c @@ -0,0 +1,446 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 SIZE_MAX > 0xFFFFFFFF + if( len <= 0xFFFFFFFF ) +#endif + { + 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 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif +} + +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; + + // 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_t unused_bits, byte_len; + + byte_len = ( bits + 7 ) / 8; + unused_bits = ( byte_len * 8 ) - bits; + + if( *p < start || (size_t)( *p - start ) < byte_len + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = byte_len + 1; + + /* Write the bitstring. Ensure the unused bits are zeroed */ + if( byte_len > 0 ) + { + byte_len--; + *--( *p ) = buf[byte_len] & ~( ( 0x1 << unused_bits ) - 1 ); + ( *p ) -= byte_len; + memcpy( *p, buf, byte_len ); + } + + /* Write unused bits */ + *--( *p ) = (unsigned char)unused_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 ); +} + + +/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(), + * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */ +static mbedtls_asn1_named_data *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 ); +} + +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 = 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 */ diff --git a/third-party/mbedtls-3.6/library/base64.c b/third-party/mbedtls-3.6/library/base64.c new file mode 100644 index 00000000..692e11e3 --- /dev/null +++ b/third-party/mbedtls-3.6/library/base64.c @@ -0,0 +1,427 @@ +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BASE64_C) + +#include "mbedtls/base64.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ + +/* + * Constant flow conditional assignment to unsigned char + */ +static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src, + unsigned char condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * 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 + + /* Generate bitmask from condition, mask will either be 0xFF or 0 */ + unsigned char mask = ( condition | -condition ); + mask >>= 7; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow conditional assignment to uint_32 + */ +static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src, + uint32_t condition ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * 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 + + /* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */ + uint32_t mask = ( condition | -condition ); + mask >>= 31; + mask = -mask; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + *dest = ( src & mask ) | ( ( *dest ) & ~mask ); +} + +/* + * Constant flow check for equality + */ +static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b ) +{ + size_t difference = in_a ^ in_b; + + /* MSVC has a warning about unary minus on unsigned integer types, + * 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 + + difference |= -difference; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* cope with the varying size of size_t per platform */ + difference >>= ( sizeof( difference ) * 8 - 1 ); + + return (unsigned char) ( 1 ^ difference ); +} + +/* + * Constant flow lookup into table. + */ +static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table, + const size_t table_size, const size_t table_index ) +{ + size_t i; + unsigned char result = 0; + + for( i = 0; i < table_size; ++i ) + { + mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) ); + } + + return result; +} + +/* + * 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++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( C3 & 0x3F ) ); + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( C1 >> 2 ) & 0x3F ) ); + + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ), + ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) ); + + if( ( i + 1 ) < slen ) + *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( 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; + unsigned char dec_map_lookup; + + /* 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 ); + + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] ); + + if( src[i] > 127 || dec_map_lookup == 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( dec_map_lookup < 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; + + dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src ); + + mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) ); + x = ( x << 6 ) | ( dec_map_lookup & 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 */ diff --git a/third-party/mbedtls-3.6/library/bignum.c b/third-party/mbedtls-3.6/library/bignum.c new file mode 100644 index 00000000..bc3491cd --- /dev/null +++ b/third-party/mbedtls-3.6/library/bignum.c @@ -0,0 +1,2708 @@ +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#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 if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + 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->n == 0 ) + { + 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 dest = src, without leaking information + * about whether the assignment was made or not. + * dest and src must be arrays of limbs of size n. + * assign must be 0 or 1. + */ +static void mpi_safe_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char assign ) +{ + size_t i; + for( i = 0; i < n; i++ ) + dest[i] = dest[i] * ( 1 - assign ) + src[i] * assign; +} + +/* + * 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; + + mpi_safe_cond_assign( Y->n, X->p, Y->p, assign ); + + for( i = Y->n; 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 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * 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, const size_t buflen ) +{ + int ret; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +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 ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + 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, buflen ) ); + } + + *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 stored_bytes = X->n * ciL; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + 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 ); +} + +/** Decide if an integer is less than the other, without branches. + * + * \param x First integer. + * \param y Second integer. + * + * \return 1 if \p x is less than \p y, 0 otherwise + */ +static unsigned ct_lt_mpi_uint( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; + + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( biL - 1 ); + + return (unsigned) ret; +} + +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; + + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; + + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; + + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; + + for( i = X->n; i > 0; i-- ) + { + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; + + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = ct_lt_mpi_uint( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + 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. + * + * Calculate d - s where d and s have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `d < s`, and 0 otherwise). + * + * \param n Number of limbs of \p d and \p s. + * \param[in,out] d On input, the left operand. + * On output, the result of the subtraction: + * \param[in] s The right operand. + * + * \return 1 if `d < s`. + * 0 if `d >= s`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *s ) +{ + 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; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret; + size_t n; + mbedtls_mpi_uint carry; + + 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; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + + carry = mpi_sub_hlp( n, X->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + { + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + --X->p[n]; + } + +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) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void 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; + + 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; + } + + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mpi_safe_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void 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; + + 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[ 1 << 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 ); + + if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || + mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) + 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( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; +#endif + + 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 ) ); + + 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 ) ); + 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++ ) + 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] ) ); + + 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 + */ + 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++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + mpi_montmul( X, &W[wbits], N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + 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, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, 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 ); + + for( i = 0; i < rounds; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + 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) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } + + if (count++ > 30) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + } 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 + */ +static int mpi_is_prime_internal( const mbedtls_mpi *X, int rounds, + 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, rounds, f_rng, p_rng ) ); +} + +/* + * Pseudo-primality test, error probability 2^-80 + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return mpi_is_prime_internal( X, 40, 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; + int rounds; + 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 ); + + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + + 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 = mpi_is_prime_internal( X, rounds, 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, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, 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 */ diff --git a/third-party/mbedtls-3.6/library/blowfish.c b/third-party/mbedtls-3.6/library/blowfish.c new file mode 100644 index 00000000..66bf355e --- /dev/null +++ b/third-party/mbedtls-3.6/library/blowfish.c @@ -0,0 +1,681 @@ +/* + * Blowfish implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#include "mbedtls/blowfish.h" + +#include + +#if !defined(MBEDTLS_BLOWFISH_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 (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 */ diff --git a/third-party/mbedtls-3.6/library/camellia.c b/third-party/mbedtls-3.6/library/camellia.c new file mode 100644 index 00000000..6ef4c213 --- /dev/null +++ b/third-party/mbedtls-3.6/library/camellia.c @@ -0,0 +1,1097 @@ +/* + * Camellia implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +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 (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 */ diff --git a/third-party/mbedtls-3.6/library/ccm.c b/third-party/mbedtls-3.6/library/ccm.c new file mode 100644 index 00000000..ed3c74c8 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ccm.c @@ -0,0 +1,504 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CCM_C) + +#include "mbedtls/ccm.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +#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 +#define CCM_SELFTEST_PT_MAX_LEN 24 +#define CCM_SELFTEST_CT_MAX_LEN 32 +/* + * 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[CCM_SELFTEST_PT_MAX_LEN] = { + 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][CCM_SELFTEST_CT_MAX_LEN] = { + { 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; + /* + * Some hardware accelerators require the input and output buffers + * would be in RAM, because the flash is not accessible. + * Use buffers on the stack to hold the test vectors data. + */ + unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN]; + unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN]; + 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 ); + + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + memset( ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN ); + memcpy( plaintext, msg, msg_len[i] ); + + ret = mbedtls_ccm_encrypt_and_tag( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + plaintext, ciphertext, + ciphertext + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( ciphertext, res[i], msg_len[i] + tag_len[i] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + memset( plaintext, 0, CCM_SELFTEST_PT_MAX_LEN ); + + ret = mbedtls_ccm_auth_decrypt( &ctx, msg_len[i], + iv, iv_len[i], ad, add_len[i], + ciphertext, plaintext, + ciphertext + msg_len[i], tag_len[i] ); + + if( ret != 0 || + memcmp( plaintext, 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 */ diff --git a/third-party/mbedtls-3.6/library/certs.c b/third-party/mbedtls-3.6/library/certs.c new file mode 100644 index 00000000..360325c8 --- /dev/null +++ b/third-party/mbedtls-3.6/library/certs.c @@ -0,0 +1,463 @@ +/* + * X.509 test certificates + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/certs.h" + +#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" + +static const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; +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 +#endif /* MBEDTLS_SHA256_C */ + +#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" + +static const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; + +#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 /* !TEST_CA_CRT_RSA_SOME */ +#endif /* !TEST_CA_CRT_RSA_COME || MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) +/* tests/data_files/server2-sha256.crt */ +#define TEST_SRV_CRT_RSA_SHA256 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\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/f8wDQYJKoZIhvcNAQELBQADggEBALVvYxsd\r\n" \ +"o5YSOIaApPlpnFUnz5zD/TbI9/63iJH+ae61jvpjTY1bqLBBEcqMMg9tVFUdt4xd\r\n" \ +"9MifL5zRZOGqKpfhWyoUZv7kXXMtfJsy0A6sqK11FcUE9r2Mt50tAO1MLZLJ5tKD\r\n" \ +"XY9/dTqXnENPxCGUo89/UwIFuNhKPUDBRMeyx8FaKsGVksF/lGxYVFWrfzZFlW0M\r\n" \ +"SXduk5xjoHE83erLEtZoxWIgrx7LXXgkDtswGkH+VpFt9dFFXJaeAQPeUBDAhEE9\r\n" \ +"UDkaCx5tPlyriwUW1w1xDx40VFV+Dgg9CFxiHCF+ppg+MG8HV0LVDRJlhN94QHNg\r\n" \ +"DAAVd5iuv8P+00Y=\r\n" \ +"-----END CERTIFICATE-----\r\n" + +const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA_SHA256; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); +#define TEST_SRV_CRT_RSA_SOME +#endif /* MBEDTLS_SHA256_C */ + +#if !defined(TEST_SRV_CRT_RSA_SOME) || defined(MBEDTLS_SHA1_C) +/* tests/data_files/server2.crt */ +#define TEST_SRV_CRT_RSA_SHA1 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDfTCCAmWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTkwMzEyMTAwNjA2WhcNMjkwMzEyMTAwNjA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" \ +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" \ +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" \ +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" \ +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" \ +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" \ +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaOBkjCBjzAd\r\n" \ +"BgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwYwYDVR0jBFwwWoAUtFrkpbPe\r\n" \ +"0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNVBAYTAk5MMREwDwYDVQQKDAhQb2xh\r\n" \ +"clNTTDEZMBcGA1UEAwwQUG9sYXJTU0wgVGVzdCBDQYIBAzAJBgNVHRMEAjAAMA0G\r\n" \ +"CSqGSIb3DQEBBQUAA4IBAQBYbmGUE3tboOInTANuIf63NHlNGw0Zx79G9Oxv8gny\r\n" \ +"oBwzIg7LGeiuIeSJXGLZ6+MVR6vjCSm4lYVFbLmrk7DRRb+JlB/9knpAtMIzT4JB\r\n" \ +"x/eDnoI9/gNO8K8pLFmNkcXBdr/QxVR+Ao/kPWHoWQtxnzfyusZlbYNvFlchORCw\r\n" \ +"m1Wcvksm9LiIXDknugnXrAc2itXY1Iq8QmyFR/SXn3IMrn1LMlwgLOl6RccliBNm\r\n" \ +"YmyNC+pRJ047hjzMIgDT0FZH3eVgJ93b3ec4bxY1tPPlAAx1QwFGnXlt67QzsLCb\r\n" \ +"WBKL+sRYcWvNwEUnwbOii6N895YciSZUnzCo53uhJq6/\r\n" \ +"-----END CERTIFICATE-----\r\n" + +#if !defined(TEST_SRV_CRT_RSA_SOME) +const char mbedtls_test_srv_crt_rsa[] = TEST_SRV_CRT_RSA_SHA1; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); +#endif /* TEST_SRV_CRT_RSA_SOME */ +#endif /* !TEST_CA_CRT_RSA_SOME || MBEDTLS_SHA1_C */ + +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; + +/* tests/data_files/server2.key */ +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 ); + +/* tests/data_files/cli-rsa-sha256.crt */ +const char mbedtls_test_cli_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTkwMzEyMTAwNDAxWhcNMjkwMzEyMTAwNDAxWjA8MQswCQYDVQQGEwJOTDERMA8G\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" +"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEDMAkGA1Ud\r\n" +"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAH78VDMNqHyxX1Tdss1Dcbx475Gei+OO\r\n" +"Pv5Z4EPLg/0Y7YgBoXI+3lM17CVhT9w5epPaSYmxzthtK0QSuJaS6Jgt7eHaQITT\r\n" +"3KXcMPqluwCy1ddr1IRYW9dXCFtgaRNJibpDuuAwf8T2tCSsY6EaYDoNgv2y6ogu\r\n" +"rh5/q7ca7Q4ENv3H+xq1V77baDa0QZijdPQ+WR+NTKPU0D8mDKlWLNSCpuItQ4Tu\r\n" +"AYzCCTosMTHlGQJ/7BkhqChH0MLTCIlUktVjY7z/4XfOWYVUMPdqUJWwfz6AgEXL\r\n" +"wjAFhq2OPrmyY2u8mrcVqpArDukPi9hOX5jzJtJaQVf4srpOL8e4nYg=\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 */ diff --git a/third-party/mbedtls-3.6/library/cipher.c b/third-party/mbedtls-3.6/library/cipher.c new file mode 100644 index 00000000..7054f4bc --- /dev/null +++ b/third-party/mbedtls-3.6/library/cipher.c @@ -0,0 +1,948 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" + +#include +#include + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* 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; +} + +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 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + else if( NULL == iv && iv_len != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( NULL == iv && iv_len == 0 ) + ctx->iv_size = 0; + + /* 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 ); + } + if ( actual_iv_size != 0 ) + { + 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 ( 0 == block_size ) + { + return( MBEDTLS_ERR_CIPHER_INVALID_CONTEXT ); + } + + 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( 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 && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + 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 ) + { + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ + copy_len = ilen % block_size; + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { + 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 */ diff --git a/third-party/mbedtls-3.6/library/cipher_wrap.c b/third-party/mbedtls-3.6/library/cipher_wrap.c new file mode 100644 index 00000000..64ce9017 --- /dev/null +++ b/third-party/mbedtls-3.6/library/cipher_wrap.c @@ -0,0 +1,1476 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher_internal.h" + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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", + 0, + 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 */ diff --git a/third-party/mbedtls-3.6/library/cmac.c b/third-party/mbedtls-3.6/library/cmac.c new file mode 100644 index 00000000..3f76344a --- /dev/null +++ b/third-party/mbedtls-3.6/library/cmac.c @@ -0,0 +1,1107 @@ +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" + +#include + + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +/* + * 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[16] ) +{ + 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 = 0; + 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 ); + } + + ret = 0; + 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 = 0; + 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" ); + } + ret = 0; + +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 */ diff --git a/third-party/mbedtls-3.6/library/ctr_drbg.c b/third-party/mbedtls-3.6/library/ctr_drbg.c new file mode 100644 index 00000000..e275f1a7 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ctr_drbg.c @@ -0,0 +1,696 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; +} + +/* + * This function resets CTR_DRBG context to the state immediately + * after initial call of mbedtls_ctr_drbg_init(). + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff f_entropy is set. */ + if( ctx->f_entropy != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; +} + +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 ) + goto exit; + + 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 ) + goto exit; + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + +exit: + mbedtls_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + int ret; + + if( add_len == 0 ) + return( 0 ); + + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + +exit: + mbedtls_zeroize( add_input, sizeof( add_input ) ); + return( ret ); +} + +/* Deprecated function, kept for backward compatibility. */ +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + /* 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; + (void) mbedtls_ctr_drbg_update_ret( ctx, additional, add_len ); +} + +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 ) + goto exit; + + /* + * Update state + */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + goto exit; + ctx->reseed_counter = 1; + +exit: + mbedtls_zeroize( seed, sizeof( seed ) ); + return( ret ); +} + +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 ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + /* The mutex is initialized iff f_entropy is set. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + ctx->entropy_len = MBEDTLS_CTR_DRBG_ENTROPY_LEN; + + /* + * 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 ); +} + +/* Backward compatibility wrapper */ +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 ) +{ + mbedtls_ctr_drbg_set_entropy_len( ctx, entropy_len ); + return( mbedtls_ctr_drbg_seed( ctx, f_entropy, p_entropy, custom, len ) ); +} + +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 ) + goto exit; + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + goto exit; + } + + 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 ) + goto exit; + + 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 ) + goto exit; + + ctx->reseed_counter++; + +exit: + mbedtls_zeroize( add_input, sizeof( add_input ) ); + mbedtls_zeroize( tmp, sizeof( tmp ) ); + return( ret ); +} + +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 + ret = mbedtls_ctr_drbg_update_ret( 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; + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, + nonce_pers_pr, 16 ) ); + 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; + mbedtls_ctr_drbg_set_entropy_len( &ctx, 32 ); + CHK( mbedtls_ctr_drbg_seed( &ctx, + ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, + nonce_pers_nopr, 16 ) ); + 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 */ diff --git a/third-party/mbedtls-3.6/library/debug.c b/third-party/mbedtls-3.6/library/debug.c new file mode 100644 index 00000000..25951eac --- /dev/null +++ b/third-party/mbedtls-3.6/library/debug.c @@ -0,0 +1,425 @@ +/* + * Debugging routines + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DEBUG_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time_t time_t +#define mbedtls_snprintf snprintf +#endif + +#include "mbedtls/debug.h" + +#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( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + 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( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + 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( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + 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( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == X || + 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( NULL == ssl || + NULL == ssl->conf || + NULL == ssl->conf->f_dbg || + NULL == crt || + 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 */ diff --git a/third-party/mbedtls-3.6/library/des.c b/third-party/mbedtls-3.6/library/des.c new file mode 100644 index 00000000..f68dba0b --- /dev/null +++ b/third-party/mbedtls-3.6/library/des.c @@ -0,0 +1,1086 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +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 (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 */ diff --git a/third-party/mbedtls-3.6/library/dhm.c b/third-party/mbedtls-3.6/library/dhm.c new file mode 100644 index 00000000..e15cc8e9 --- /dev/null +++ b/third-party/mbedtls-3.6/library/dhm.c @@ -0,0 +1,716 @@ +/* + * Diffie-Hellman-Merkle key exchange + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DHM_C) + +#include "mbedtls/dhm.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 ); +} + +/* + * Pick a random R in the range [2, M) for blinding purposes + */ +static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count; + + count = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 ); + +cleanup: + return( ret ); +} + + +/* + * 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; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + /* + * 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 ) */ + MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) ); + + /* Vf = Vi^-X mod P + * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod), + * then elevate to the Xth power. */ + MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); + +cleanup: + mbedtls_mpi_free( &R ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/ecdh.c b/third-party/mbedtls-3.6/library/ecdh.c new file mode 100644 index 00000000..a8ff5b94 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ecdh.c @@ -0,0 +1,305 @@ +/* + * Elliptic curve Diffie-Hellman + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * RFC 4492 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDH_C) + +#include "mbedtls/ecdh.h" + +#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( ctx->grp.id == MBEDTLS_ECP_DP_NONE ) + { + /* This is the first call to get_params(). Copy the group information + * into the context. */ + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ) + return( ret ); + } + else + { + /* This is not the first call to get_params(). Check that the group + * is the same as the first time. */ + if( ctx->grp.id != key->grp.id ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + /* 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 */ diff --git a/third-party/mbedtls-3.6/library/ecdsa.c b/third-party/mbedtls-3.6/library/ecdsa.c new file mode 100644 index 00000000..59803d04 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ecdsa.c @@ -0,0 +1,575 @@ +/* + * Elliptic curve DSA + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#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) + */ +static int ecdsa_sign_internal( 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 (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + 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_privkey( grp, &k, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &R, &k, &grp->G, + f_rng_blind, p_rng_blind ) ); + 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. + * + * This loop does the same job as mbedtls_ecp_gen_privkey() and it is + * replaced by a call to it in the mainline. This change is not + * necessary to backport the fix separating the blinding and ephemeral + * key generating RNGs, therefore the original code is kept. + */ + blind_tries = 0; + do + { + size_t n_size = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng_blind, + p_rng_blind ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); + + 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_mod_mpi( &k, &k, &grp->N ) ); + 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 ); +} + +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 ) +{ + /* Use the same RNG for both blinding and ephemeral key generation */ + return( ecdsa_sign_internal( grp, r, s, d, buf, blen, f_rng, p_rng, + f_rng, p_rng ) ); +} +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +static int ecdsa_sign_det_internal( 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 (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + 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; + /* Variables for deterministic blinding fallback */ + const char* blind_label = "BLINDING CONTEXT"; + mbedtls_hmac_drbg_context rng_ctx_blind; + + 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 ); + mbedtls_hmac_drbg_init( &rng_ctx_blind ); + + /* 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 ); + + if( f_rng_blind != NULL ) + ret = ecdsa_sign_internal( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, &rng_ctx, + f_rng_blind, p_rng_blind ); + else + { + /* + * To avoid reusing rng_ctx and risking incorrect behavior we seed a + * second HMAC-DRBG with the same seed. We also apply a label to avoid + * reusing the bits of the ephemeral key for blinding and eliminate the + * risk that they leak this way. + */ + + mbedtls_hmac_drbg_seed_buf( &rng_ctx_blind, md_info, + data, 2 * grp_len ); + ret = mbedtls_hmac_drbg_update_ret( &rng_ctx_blind, + (const unsigned char*) blind_label, + strlen( blind_label ) ); + if( ret != 0 ) + goto cleanup; + + /* + * Since the output of the RNGs is always the same for the same key and + * message, this limits the efficiency of blinding and leaks information + * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL + * won't be a valid value for f_rng_blind anymore. Therefore it should + * be checked by the caller and this branch and check can be removed. + */ + ret = ecdsa_sign_internal( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, &rng_ctx, + mbedtls_hmac_drbg_random, &rng_ctx_blind ); + + } + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_hmac_drbg_free( &rng_ctx_blind ); + mbedtls_mpi_free( &h ); + + return( ret ); +} + +/* + * Deterministic signature wrappers + */ +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 ) +{ + return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg, + NULL, NULL ) ); +} + +int mbedtls_ecdsa_sign_det_ext( 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 (*f_rng_blind)(void *, unsigned char *, + size_t), + void *p_rng_blind ) +{ + return( ecdsa_sign_det_internal( grp, r, s, d, buf, blen, md_alg, + f_rng_blind, p_rng_blind ) ); +} +#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) + MBEDTLS_MPI_CHK( ecdsa_sign_det_internal( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, + f_rng, p_rng ) ); +#else + (void) md_alg; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + + 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; + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + 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 ) +{ + int ret = 0; + ret = mbedtls_ecp_group_load( &ctx->grp, gid ); + if( ret != 0 ) + return( ret ); + + return( 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 */ diff --git a/third-party/mbedtls-3.6/library/ecjpake.c b/third-party/mbedtls-3.6/library/ecjpake.c new file mode 100644 index 00000000..a6f50838 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ecjpake.c @@ -0,0 +1,1131 @@ +/* + * Elliptic curve J-PAKE + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECJPAKE_C) + +#include "mbedtls/ecjpake.h" + +#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_MPI_CHK( 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) +#include "mbedtls/platform.h" +#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 corresponding 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 */ diff --git a/third-party/mbedtls-3.6/library/ecp.c b/third-party/mbedtls-3.6/library/ecp.c new file mode 100644 index 00000000..897c01e1 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ecp.c @@ -0,0 +1,2633 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/threading.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ecp_internal.h" + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#elif defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#elif defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#elif defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#else +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#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_NO_INTERNAL_RNG) +/* + * Currently ecp_mul() takes a RNG function as an argument, used for + * side-channel protection, but it can be NULL. The initial reasoning was + * that people will pass non-NULL RNG when they care about side-channels, but + * unfortunately we have some APIs that call ecp_mul() with a NULL RNG, with + * no opportunity for the user to do anything about it. + * + * The obvious strategies for addressing that include: + * - change those APIs so that they take RNG arguments; + * - require a global RNG to be available to all crypto modules. + * + * Unfortunately those would break compatibility. So what we do instead is + * have our own internal DRBG instance, seeded from the secret scalar. + * + * The following is a light-weight abstraction layer for doing that with + * HMAC_DRBG (first choice) or CTR_DRBG. + */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_hmac_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_hmac_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_hmac_drbg_random( p_rng, output, output_len ) ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + /* The list starts with strong hashes */ + const mbedtls_md_type_t md_type = mbedtls_md_list()[0]; + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_type ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_hmac_drbg_seed_buf( ctx, md_info, secret_bytes, secret_len ); + +cleanup: + mbedtls_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_CTR_DRBG_C) + +/* DRBG context type */ +typedef mbedtls_ctr_drbg_context ecp_drbg_context; + +/* DRBG context init */ +static inline void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_init( ctx ); +} + +/* DRBG context free */ +static inline void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_ctr_drbg_free( ctx ); +} + +/* DRBG function */ +static inline int ecp_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ) +{ + return( mbedtls_ctr_drbg_random( p_rng, output, output_len ) ); +} + +/* + * Since CTR_DRBG doesn't have a seed_buf() function the way HMAC_DRBG does, + * we need to pass an entropy function when seeding. So we use a dummy + * function for that, and pass the actual entropy as customisation string. + * (During seeding of CTR_DRBG the entropy input and customisation string are + * concatenated before being used to update the secret state.) + */ +static int ecp_ctr_drbg_null_entropy(void *ctx, unsigned char *out, size_t len) +{ + (void) ctx; + memset( out, 0, len ); + return( 0 ); +} + +/* DRBG context seeding */ +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + int ret; + unsigned char secret_bytes[MBEDTLS_ECP_MAX_BYTES]; + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( secret, + secret_bytes, secret_len ) ); + + ret = mbedtls_ctr_drbg_seed( ctx, ecp_ctr_drbg_null_entropy, NULL, + secret_bytes, secret_len ); + +cleanup: + mbedtls_zeroize( secret_bytes, secret_len ); + + return( ret ); +} + +#elif defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_SHA256_C) + +/* This will be used in the self-test function */ +#define ECP_ONE_STEP_KDF + +/* + * We need to expand secret data (the scalar) into a longer stream of bytes. + * + * We'll use the One-Step KDF from NIST SP 800-56C, with option 1 (H is a hash + * function) and empty FixedInfo. (Though we'll make it fit the DRBG API for + * convenience, this is not a full-fledged DRBG, but we don't need one here.) + * + * We need a basic hash abstraction layer to use whatever SHA-2 is available. + */ +#if defined(MBEDTLS_SHA512_C) + +#define HASH_FUNC( in, ilen, out ) mbedtls_sha512_ret( in, ilen, out, 0 ); +#define HASH_BLOCK_BYTES ( 512 / 8 ) + +#elif defined(MBEDTLS_SHA256_C) + +#define HASH_FUNC( in, ilen, out ) mbedtls_sha256_ret( in, ilen, out, 0 ); +#define HASH_BLOCK_BYTES ( 256 / 8 ) + +#endif /* SHA512/SHA256 abstraction */ + +/* + * State consists of a 32-bit counter plus the secret value. + * + * We stored them concatenated in a single buffer as that's what will get + * passed to the hash function. + */ +typedef struct { + size_t total_len; + uint8_t buf[4 + MBEDTLS_ECP_MAX_BYTES]; +} ecp_drbg_context; + +static void ecp_drbg_init( ecp_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( ecp_drbg_context ) ); +} + +static void ecp_drbg_free( ecp_drbg_context *ctx ) +{ + mbedtls_zeroize( ctx, sizeof( ecp_drbg_context ) ); +} + +static int ecp_drbg_seed( ecp_drbg_context *ctx, + const mbedtls_mpi *secret, size_t secret_len ) +{ + ctx->total_len = 4 + secret_len; + memset( ctx->buf, 0, 4); + return( mbedtls_mpi_write_binary( secret, ctx->buf + 4, secret_len ) ); +} + +static int ecp_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + ecp_drbg_context *ctx = p_rng; + int ret; + size_t len_done = 0; + uint8_t tmp[HASH_BLOCK_BYTES]; + + while( len_done < output_len ) + { + uint8_t use_len; + + /* This function is only called for coordinate randomisation, which + * happens only twice in a scalar multiplication. Each time needs a + * random value in the range [2, p-1], and gets it by drawing len(p) + * bytes from this function, and retrying up to 10 times if unlucky. + * + * So for the largest curve, each scalar multiplication draws at most + * 20 * 66 bytes. The minimum block size is 32 (SHA-256), so with + * rounding that means a most 20 * 3 blocks. + * + * Since we don't need to draw more that 255 blocks, don't bother + * with carry propagation and just return an error instead. We can + * change that it we even need to draw more blinding values. + */ + ctx->buf[3] += 1; + if( ctx->buf[3] == 0 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + + ret = HASH_FUNC( ctx->buf, ctx->total_len, tmp ); + if( ret != 0 ) + return( ret ); + + if( output_len - len_done > HASH_BLOCK_BYTES ) + use_len = HASH_BLOCK_BYTES; + else + use_len = output_len - len_done; + + memcpy( output + len_done, tmp, use_len ); + len_done += use_len; + } + + mbedtls_zeroize( tmp, sizeof( tmp ) ); + + return( 0 ); +} + +#else /* DRBG/SHA modules */ +#error "Invalid configuration detected. Include check_config.h to ensure that the configuration is valid." +#endif /* DRBG/SHA modules */ +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#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 lazily + */ +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 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + 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 defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + 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 ) ); + + /* + * Knowledge of the jacobian coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != 0 ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + /* There are two cases where T is not stored in grp: + * - P != G + * - An intermediate operation failed before setting grp->T + * In either case, T must be freed. + */ + if( T != NULL && T != grp->T ) + { + 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 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + 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 defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + 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 ) ); + } + + /* + * Knowledge of the projective coordinates may leak the last few bits of the + * scalar [1], and since our MPI implementation isn't constant-flow, + * inversion (used for coordinate normalization) may leak the full value + * of its input via side-channels [2]. + * + * [1] https://eprint.iacr.org/2003/191 + * [2] https://eprint.iacr.org/2020/055 + * + * Avoid the leak by randomizing coordinates before we normalize them. + */ +#if defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + if( f_rng != NULL ) +#endif + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, R, f_rng, p_rng ) ); + + 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 +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_context drbg_ctx; + + ecp_drbg_init( &drbg_ctx ); +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + + /* 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_NO_INTERNAL_RNG) + if( f_rng == NULL ) + { + const size_t m_len = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( ecp_drbg_seed( &drbg_ctx, m, m_len ) ); + f_rng = &ecp_drbg_random; + p_rng = &drbg_ctx; + } +#endif /* !MBEDTLS_ECP_NO_INTERNAL_RNG */ + +#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) || !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) +cleanup: +#endif +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if !defined(MBEDTLS_ECP_NO_INTERNAL_RNG) + ecp_drbg_free( &drbg_ctx ); +#endif + + 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 private key + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + 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 ) ); + } +#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; + unsigned cmp = 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 ); + + ret = mbedtls_mpi_lt_mpi_ct( d, &grp->N, &cmp ); + if( ret != 0 ) + { + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || cmp != 1 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + +cleanup: + return( ret ); +} + +/* + * 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; + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); +} + +/* + * 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) + +#if defined(ECP_ONE_STEP_KDF) +/* + * There are no test vectors from NIST for the One-Step KDF in SP 800-56C, + * but unofficial ones can be found at: + * https://github.com/patrickfav/singlestep-kdf/wiki/NIST-SP-800-56C-Rev1:-Non-Official-Test-Vectors + * + * We only use the ones with empty fixedInfo, and for brevity's sake, only + * 40-bytes output (with SHA-256 that's more than one block, and with SHA-512 + * less than one block). + */ +#if defined(MBEDTLS_SHA512_C) + +static const uint8_t test_kdf_z[16] = { + 0x3b, 0xa9, 0x79, 0xe9, 0xbc, 0x5e, 0x3e, 0xc7, + 0x61, 0x30, 0x36, 0xb6, 0xf5, 0x1c, 0xd5, 0xaa, +}; +static const uint8_t test_kdf_out[40] = { + 0x3e, 0xf6, 0xda, 0xf9, 0x51, 0x60, 0x70, 0x5f, + 0xdf, 0x21, 0xcd, 0xab, 0xac, 0x25, 0x7b, 0x05, + 0xfe, 0xc1, 0xab, 0x7c, 0xc9, 0x68, 0x43, 0x25, + 0x8a, 0xfc, 0x40, 0x6e, 0x5b, 0xf7, 0x98, 0x27, + 0x10, 0xfa, 0x7b, 0x93, 0x52, 0xd4, 0x16, 0xaa, +}; + +#elif defined(MBEDTLS_SHA256_C) + +static const uint8_t test_kdf_z[16] = { + 0xc8, 0x3e, 0x35, 0x8e, 0x99, 0xa6, 0x89, 0xc6, + 0x7d, 0xb4, 0xfe, 0x39, 0xcf, 0x8f, 0x26, 0xe1, +}; +static const uint8_t test_kdf_out[40] = { + 0x7d, 0xf6, 0x41, 0xf8, 0x3c, 0x47, 0xdc, 0x28, + 0x5f, 0x7f, 0xaa, 0xde, 0x05, 0x64, 0xd6, 0x25, + 0x00, 0x6a, 0x47, 0xd9, 0x1e, 0xa4, 0xa0, 0x8c, + 0xd7, 0xf7, 0x0c, 0x99, 0xaa, 0xa0, 0x72, 0x66, + 0x69, 0x0e, 0x25, 0xaa, 0xa1, 0x63, 0x14, 0x79, +}; + +#endif + +static int ecp_kdf_self_test( void ) +{ + int ret; + ecp_drbg_context kdf_ctx; + mbedtls_mpi scalar; + uint8_t out[sizeof( test_kdf_out )]; + + ecp_drbg_init( &kdf_ctx ); + mbedtls_mpi_init( &scalar ); + memset( out, 0, sizeof( out ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &scalar, + test_kdf_z, sizeof( test_kdf_z ) ) ); + + MBEDTLS_MPI_CHK( ecp_drbg_seed( &kdf_ctx, + &scalar, sizeof( test_kdf_z ) ) ); + + MBEDTLS_MPI_CHK( ecp_drbg_random( &kdf_ctx, out, sizeof( out ) ) ); + + if( memcmp( out, test_kdf_out, sizeof( out ) ) != 0 ) + ret = -1; + +cleanup: + ecp_drbg_free( &kdf_ctx ); + mbedtls_mpi_free( &scalar ); + + return( ret ); +} +#endif /* ECP_ONE_STEP_KDF */ + +/* + * 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" ); + +#if defined(ECP_ONE_STEP_KDF) + if( verbose != 0 ) + mbedtls_printf( " ECP test #3 (internal KDF): " ); + + ret = ecp_kdf_self_test(); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* ECP_ONE_STEP_KDF */ + +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 */ diff --git a/third-party/mbedtls-3.6/library/ecp_curves.c b/third-party/mbedtls-3.6/library/ecp_curves.c new file mode 100644 index 00000000..93315870 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ecp_curves.c @@ -0,0 +1,1354 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" + +#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 ) MBEDTLS_MPI_CHK( 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 */ diff --git a/third-party/mbedtls-3.6/library/entropy.c b/third-party/mbedtls-3.6/library/entropy.c new file mode 100644 index 00000000..fb5e0eca --- /dev/null +++ b/third-party/mbedtls-3.6/library/entropy.c @@ -0,0 +1,755 @@ +/* + * Entropy accumulator implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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 "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#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 the context was already free, don't call free() again. + * This is important for mutexes which don't allow double-free. */ + if( ctx->accumulator_started == -1 ) + return; + +#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 = -1; +} + +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 */ diff --git a/third-party/mbedtls-3.6/library/entropy_poll.c b/third-party/mbedtls-3.6/library/entropy_poll.c new file mode 100644 index 00000000..dbb57008 --- /dev/null +++ b/third-party/mbedtls-3.6/library/entropy_poll.c @@ -0,0 +1,254 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#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 +#include + +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 ) ); +} +#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; + int ret; + ((void) data); + +#if defined(HAVE_GETRANDOM) + ret = getrandom_wrapper( output, len, 0 ); + if( ret >= 0 ) + { + *olen = ret; + return( 0 ); + } + else if( errno != ENOSYS ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + /* Fall through if the system call isn't known. */ +#else + ((void) ret); +#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 */ diff --git a/third-party/mbedtls-3.6/library/error.c b/third-party/mbedtls-3.6/library/error.c new file mode 100644 index 00000000..9b04dcd2 --- /dev/null +++ b/third-party/mbedtls-3.6/library/error.c @@ -0,0 +1,850 @@ +/* + * Error message information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +#include "mbedtls/error.h" + +#if defined(MBEDTLS_ERROR_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#include +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#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 - The buffer contains a valid signature followed by more data" ); + 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 buffer contains a valid signature followed by more data" ); + 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" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_CONFIG) ) + mbedtls_snprintf( buf, buflen, "SSL - Invalid value in SSL config" ); +#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 occurred, 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 */ + +/* + * 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_C */ + +#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */ diff --git a/third-party/mbedtls-3.6/library/gcm.c b/third-party/mbedtls-3.6/library/gcm.c new file mode 100644 index 00000000..a7e67063 --- /dev/null +++ b/third-party/mbedtls-3.6/library/gcm.c @@ -0,0 +1,983 @@ +/* + * NIST SP800-38D compliant GCM implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_GCM_C) + +#include "mbedtls/gcm.h" + +#include + +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 */ diff --git a/third-party/mbedtls-3.6/library/havege.c b/third-party/mbedtls-3.6/library/havege.c new file mode 100644 index 00000000..8d106df8 --- /dev/null +++ b/third-party/mbedtls-3.6/library/havege.c @@ -0,0 +1,282 @@ +/** + * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVEGE_C) + +#include "mbedtls/havege.h" +#include "mbedtls/timing.h" + +#include +#include + +/* If int isn't capable of storing 2^32 distinct values, the code of this + * module may cause a processor trap or a miscalculation. If int is more + * than 32 bits, the code may not calculate the intended values. */ +#if INT_MIN + 1 != -0x7fffffff +#error "The HAVEGE module requires int to be exactly 32 bits, with INT_MIN = -2^31." +#endif +#if UINT_MAX != 0xffffffff +#error "The HAVEGE module requires unsigned to be exactly 32 bits." +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* ------------------------------------------------------------------------ + * 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) { unsigned *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 = (unsigned) 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 = (unsigned) 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++ ) \ + POOL[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; + +/* + * Entropy gathering function + */ +static void havege_fill( mbedtls_havege_state *hs ) +{ + unsigned i, n = 0; + unsigned U1, U2, *A, *B, *C, *D; + unsigned PT1, PT2, *WALK, *POOL, RES[16]; + unsigned PTX, PTY, CLK, PTEST, IN; + + WALK = (unsigned *) hs->WALK; + POOL = (unsigned *) hs->pool; + 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 */ diff --git a/third-party/mbedtls-3.6/library/hmac_drbg.c b/third-party/mbedtls-3.6/library/hmac_drbg.c new file mode 100644 index 00000000..876fa574 --- /dev/null +++ b/third-party/mbedtls-3.6/library/hmac_drbg.c @@ -0,0 +1,660 @@ +/* + * HMAC_DRBG implementation (NIST SP 800-90) + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) + +#include "mbedtls/hmac_drbg.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * HMAC_DRBG context initialization + */ +void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_hmac_drbg_context ) ); + + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +/* + * HMAC_DRBG update, using optional additional data (10.1.2.2) + */ +int mbedtls_hmac_drbg_update_ret( 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]; + int ret; + + for( sep[0] = 0; sep[0] < rounds; sep[0]++ ) + { + /* Step 1 or 4 */ + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + sep, 1 ) ) != 0 ) + goto exit; + if( rounds == 2 ) + { + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, K ) ) != 0 ) + goto exit; + + /* Step 2 or 5 */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, K, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + } + +exit: + mbedtls_zeroize( K, sizeof( K ) ); + return( ret ); +} + +void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, + size_t add_len ) +{ + (void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len ); +} + +/* + * 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 ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + /* + * 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. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, + mbedtls_md_get_size( md_info ) ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, mbedtls_md_get_size( md_info ) ); + + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, data, data_len ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * Internal function used both for seeding and reseeding the DRBG. + * Comments starting with arabic numbers refer to section 10.1.2.4 + * of SP800-90A, while roman numbers refer to section 9.2. + */ +static int hmac_drbg_reseed_core( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len, + int use_nonce ) +{ + unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret; + + { + size_t total_entropy_len; + + if( use_nonce == 0 ) + total_entropy_len = ctx->entropy_len; + else + total_entropy_len = ctx->entropy_len * 3 / 2; + + /* III. Check input length */ + if( len > MBEDTLS_HMAC_DRBG_MAX_INPUT || + total_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( ( ret = ctx->f_entropy( ctx->p_entropy, + seed, ctx->entropy_len ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + seedlen += ctx->entropy_len; + + /* For initial seeding, allow adding of nonce generated + * from the entropy source. See Sect 8.6.7 in SP800-90A. */ + if( use_nonce ) + { + /* Note: We don't merge the two calls to f_entropy() in order + * to avoid requesting too much entropy from f_entropy() + * at once. Specifically, if the underlying digest is not + * SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which + * is larger than the maximum of 32 Bytes that our own + * entropy source implementation can emit in a single + * call in configurations disabling SHA-512. */ + if( ( ret = ctx->f_entropy( ctx->p_entropy, + seed + seedlen, + ctx->entropy_len / 2 ) ) != 0 ) + { + return( MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len / 2; + } + + + /* 1. Concatenate entropy and additional data if any */ + if( additional != NULL && len != 0 ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* 2. Update state */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, seed, seedlen ) ) != 0 ) + goto exit; + + /* 3. Reset reseed_counter */ + ctx->reseed_counter = 1; + +exit: + /* 4. Done */ + mbedtls_zeroize( seed, seedlen ); + return( ret ); +} + +/* + * HMAC_DRBG reseeding: 10.1.2.4 + 9.2 + */ +int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + return( hmac_drbg_reseed_core( ctx, additional, len, 0 ) ); +} + +/* + * HMAC_DRBG initialisation (10.1.2.3 + 9.1) + * + * The nonce is not passed as a separate parameter but extracted + * from the entropy source as suggested in 8.6.7. + */ +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 md_size; + + if( ( ret = mbedtls_md_setup( &ctx->md_ctx, md_info, 1 ) ) != 0 ) + return( ret ); + + /* The mutex is initialized iff the md context is set up. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + 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. + */ + if( ( ret = mbedtls_md_hmac_starts( &ctx->md_ctx, ctx->V, md_size ) ) != 0 ) + return( ret ); + memset( ctx->V, 0x01, md_size ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + if( ctx->entropy_len == 0 ) + { + /* + * 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.) + */ + ctx->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 */ + } + + if( ( ret = hmac_drbg_reseed_core( ctx, custom, len, + 1 /* add nonce */ ) ) != 0 ) + { + return( ret ); + } + + 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 seeding + */ +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 ) + { + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + } + + /* 3, 4, 5. Generate bytes */ + while( left != 0 ) + { + size_t use_len = left > md_len ? md_len : left; + + if( ( ret = mbedtls_md_hmac_reset( &ctx->md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_update( &ctx->md_ctx, + ctx->V, md_len ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_hmac_finish( &ctx->md_ctx, ctx->V ) ) != 0 ) + goto exit; + + memcpy( out, ctx->V, use_len ); + out += use_len; + left -= use_len; + } + + /* 6. Update */ + if( ( ret = mbedtls_hmac_drbg_update_ret( ctx, + additional, add_len ) ) != 0 ) + goto exit; + + /* 7. Update reseed counter */ + ctx->reseed_counter++; + +exit: + /* 8. Done */ + return( ret ); +} + +/* + * 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 ); +} + +/* + * This function resets HMAC_DRBG context to the state immediately + * after initial call of mbedtls_hmac_drbg_init(). + */ +void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + /* The mutex is initialized iff the md context is set up. */ + if( ctx->md_ctx.md_info != NULL ) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_md_free( &ctx->md_ctx ); + mbedtls_zeroize( ctx, sizeof( mbedtls_hmac_drbg_context ) ); + ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL; +} + +#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 + ret = mbedtls_hmac_drbg_update_ret( 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 */ diff --git a/third-party/mbedtls-3.6/library/md.c b/third-party/mbedtls-3.6/library/md.c new file mode 100644 index 00000000..ba48471c --- /dev/null +++ b/third-party/mbedtls-3.6/library/md.c @@ -0,0 +1,503 @@ +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 */ diff --git a/third-party/mbedtls-3.6/library/md2.c b/third-party/mbedtls-3.6/library/md2.c new file mode 100644 index 00000000..eb4d0d03 --- /dev/null +++ b/third-party/mbedtls-3.6/library/md2.c @@ -0,0 +1,395 @@ +/* + * RFC 1115/1319 compliant MD2 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD2_C) + +#include "mbedtls/md2.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +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]; + } + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_zeroize( &t, sizeof( t ) ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/md4.c b/third-party/mbedtls-3.6/library/md4.c new file mode 100644 index 00000000..160a8149 --- /dev/null +++ b/third-party/mbedtls-3.6/library/md4.c @@ -0,0 +1,503 @@ +/* + * RFC 1186/1320 compliant MD4 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD4_C) + +#include "mbedtls/md4.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = 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 + +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] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + GET_UINT32_LE( local.X[ 0], data, 0 ); + GET_UINT32_LE( local.X[ 1], data, 4 ); + GET_UINT32_LE( local.X[ 2], data, 8 ); + GET_UINT32_LE( local.X[ 3], data, 12 ); + GET_UINT32_LE( local.X[ 4], data, 16 ); + GET_UINT32_LE( local.X[ 5], data, 20 ); + GET_UINT32_LE( local.X[ 6], data, 24 ); + GET_UINT32_LE( local.X[ 7], data, 28 ); + GET_UINT32_LE( local.X[ 8], data, 32 ); + GET_UINT32_LE( local.X[ 9], data, 36 ); + GET_UINT32_LE( local.X[10], data, 40 ); + GET_UINT32_LE( local.X[11], data, 44 ); + GET_UINT32_LE( local.X[12], data, 48 ); + GET_UINT32_LE( local.X[13], data, 52 ); + GET_UINT32_LE( local.X[14], data, 56 ); + GET_UINT32_LE( local.X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.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( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 1], 7 ); + P( local.C, local.D, local.A, local.B, local.X[ 2], 11 ); + P( local.B, local.C, local.D, local.A, local.X[ 3], 19 ); + P( local.A, local.B, local.C, local.D, local.X[ 4], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 5], 7 ); + P( local.C, local.D, local.A, local.B, local.X[ 6], 11 ); + P( local.B, local.C, local.D, local.A, local.X[ 7], 19 ); + P( local.A, local.B, local.C, local.D, local.X[ 8], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 9], 7 ); + P( local.C, local.D, local.A, local.B, local.X[10], 11 ); + P( local.B, local.C, local.D, local.A, local.X[11], 19 ); + P( local.A, local.B, local.C, local.D, local.X[12], 3 ); + P( local.D, local.A, local.B, local.C, local.X[13], 7 ); + P( local.C, local.D, local.A, local.B, local.X[14], 11 ); + P( local.B, local.C, local.D, local.A, local.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( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 4], 5 ); + P( local.C, local.D, local.A, local.B, local.X[ 8], 9 ); + P( local.B, local.C, local.D, local.A, local.X[12], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 1], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 5], 5 ); + P( local.C, local.D, local.A, local.B, local.X[ 9], 9 ); + P( local.B, local.C, local.D, local.A, local.X[13], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 2], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 6], 5 ); + P( local.C, local.D, local.A, local.B, local.X[10], 9 ); + P( local.B, local.C, local.D, local.A, local.X[14], 13 ); + P( local.A, local.B, local.C, local.D, local.X[ 3], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 7], 5 ); + P( local.C, local.D, local.A, local.B, local.X[11], 9 ); + P( local.B, local.C, local.D, local.A, local.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( local.A, local.B, local.C, local.D, local.X[ 0], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 8], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 4], 11 ); + P( local.B, local.C, local.D, local.A, local.X[12], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 2], 3 ); + P( local.D, local.A, local.B, local.C, local.X[10], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 6], 11 ); + P( local.B, local.C, local.D, local.A, local.X[14], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 1], 3 ); + P( local.D, local.A, local.B, local.C, local.X[ 9], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 5], 11 ); + P( local.B, local.C, local.D, local.A, local.X[13], 15 ); + P( local.A, local.B, local.C, local.D, local.X[ 3], 3 ); + P( local.D, local.A, local.B, local.C, local.X[11], 9 ); + P( local.C, local.D, local.A, local.B, local.X[ 7], 11 ); + P( local.B, local.C, local.D, local.A, local.X[15], 15 ); + +#undef F +#undef P + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_zeroize( &local, sizeof( local ) ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/md5.c b/third-party/mbedtls-3.6/library/md5.c new file mode 100644 index 00000000..125406f1 --- /dev/null +++ b/third-party/mbedtls-3.6/library/md5.c @@ -0,0 +1,530 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = 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 + +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] ) +{ + struct + { + uint32_t X[16], A, B, C, D; + } local; + + GET_UINT32_LE( local.X[ 0], data, 0 ); + GET_UINT32_LE( local.X[ 1], data, 4 ); + GET_UINT32_LE( local.X[ 2], data, 8 ); + GET_UINT32_LE( local.X[ 3], data, 12 ); + GET_UINT32_LE( local.X[ 4], data, 16 ); + GET_UINT32_LE( local.X[ 5], data, 20 ); + GET_UINT32_LE( local.X[ 6], data, 24 ); + GET_UINT32_LE( local.X[ 7], data, 28 ); + GET_UINT32_LE( local.X[ 8], data, 32 ); + GET_UINT32_LE( local.X[ 9], data, 36 ); + GET_UINT32_LE( local.X[10], data, 40 ); + GET_UINT32_LE( local.X[11], data, 44 ); + GET_UINT32_LE( local.X[12], data, 48 ); + GET_UINT32_LE( local.X[13], data, 52 ); + GET_UINT32_LE( local.X[14], data, 56 ); + GET_UINT32_LE( local.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) + local.X[k] + t; a = S(a,s) + b; \ +} + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478 ); + P( local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756 ); + P( local.C, local.D, local.A, local.B, 2, 17, 0x242070DB ); + P( local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE ); + P( local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF ); + P( local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A ); + P( local.C, local.D, local.A, local.B, 6, 17, 0xA8304613 ); + P( local.B, local.C, local.D, local.A, 7, 22, 0xFD469501 ); + P( local.A, local.B, local.C, local.D, 8, 7, 0x698098D8 ); + P( local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF ); + P( local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1 ); + P( local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE ); + P( local.A, local.B, local.C, local.D, 12, 7, 0x6B901122 ); + P( local.D, local.A, local.B, local.C, 13, 12, 0xFD987193 ); + P( local.C, local.D, local.A, local.B, 14, 17, 0xA679438E ); + P( local.B, local.C, local.D, local.A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562 ); + P( local.D, local.A, local.B, local.C, 6, 9, 0xC040B340 ); + P( local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51 ); + P( local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA ); + P( local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D ); + P( local.D, local.A, local.B, local.C, 10, 9, 0x02441453 ); + P( local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681 ); + P( local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8 ); + P( local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6 ); + P( local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6 ); + P( local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87 ); + P( local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED ); + P( local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905 ); + P( local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8 ); + P( local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9 ); + P( local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942 ); + P( local.D, local.A, local.B, local.C, 8, 11, 0x8771F681 ); + P( local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122 ); + P( local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C ); + P( local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44 ); + P( local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9 ); + P( local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60 ); + P( local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70 ); + P( local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6 ); + P( local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA ); + P( local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085 ); + P( local.B, local.C, local.D, local.A, 6, 23, 0x04881D05 ); + P( local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039 ); + P( local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5 ); + P( local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8 ); + P( local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( local.A, local.B, local.C, local.D, 0, 6, 0xF4292244 ); + P( local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97 ); + P( local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7 ); + P( local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039 ); + P( local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3 ); + P( local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92 ); + P( local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D ); + P( local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1 ); + P( local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F ); + P( local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0 ); + P( local.C, local.D, local.A, local.B, 6, 15, 0xA3014314 ); + P( local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1 ); + P( local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82 ); + P( local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235 ); + P( local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB ); + P( local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_zeroize( &local, sizeof( local ) ); + + 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 + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + 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 */ diff --git a/third-party/mbedtls-3.6/library/md_wrap.c b/third-party/mbedtls-3.6/library/md_wrap.c new file mode 100644 index 00000000..7459db2f --- /dev/null +++ b/third-party/mbedtls-3.6/library/md_wrap.c @@ -0,0 +1,611 @@ +/** + * \file md_wrap.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ diff --git a/third-party/mbedtls-3.6/library/memory_buffer_alloc.c b/third-party/mbedtls-3.6/library/memory_buffer_alloc.c new file mode 100644 index 00000000..dc8b4bf0 --- /dev/null +++ b/third-party/mbedtls-3.6/library/memory_buffer_alloc.c @@ -0,0 +1,779 @@ +/* + * Buffer-based memory allocator + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" + +/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C + is dependent upon MBEDTLS_PLATFORM_C */ +#include "mbedtls/platform.h" + +#include + +#if defined(MBEDTLS_MEMORY_BACKTRACE) +#include +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#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() +{ + 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() +{ + 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() +{ + return verify_chain(); +} + +#if defined(MBEDTLS_MEMORY_DEBUG) +void mbedtls_memory_buffer_alloc_status() +{ + 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() +{ +#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( ) +{ + 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 */ diff --git a/third-party/mbedtls-3.6/library/net_sockets.c b/third-party/mbedtls-3.6/library/net_sockets.c new file mode 100644 index 00000000..fa27603c --- /dev/null +++ b/third-party/mbedtls-3.6/library/net_sockets.c @@ -0,0 +1,625 @@ +/* + * TCP/IP or UDP/IP networking functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#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) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/net_sockets.h" + +#include + +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) + +#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) +#undef _WIN32_WINNT +/* Enables getaddrinfo() & Co */ +#define _WIN32_WINNT 0x0501 +#endif + +#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 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) || \ + ( defined(__NetBSD__) && 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 ); + + /* A limitation of select() is that it only works with file descriptors + * that are strictly less than FD_SETSIZE. This is a limitation of the + * fd_set type. Error out early, because attempting to call FD_SET on a + * large file descriptor is a buffer overflow on typical platforms. */ + if( fd >= FD_SETSIZE ) + return( MBEDTLS_ERR_NET_RECV_FAILED ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/oid.c b/third-party/mbedtls-3.6/library/oid.c new file mode 100644 index 00000000..ad2c3222 --- /dev/null +++ b/third-party/mbedtls-3.6/library/oid.c @@ -0,0 +1,780 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#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 */ diff --git a/third-party/mbedtls-3.6/library/padlock.c b/third-party/mbedtls-3.6/library/padlock.c new file mode 100644 index 00000000..afb7e0ad --- /dev/null +++ b/third-party/mbedtls-3.6/library/padlock.c @@ -0,0 +1,195 @@ +/* + * VIA PadLock support functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PADLOCK_C) + +#include "mbedtls/padlock.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/library/pem.c b/third-party/mbedtls-3.6/library/pem.c new file mode 100644 index 00000000..8c070487 --- /dev/null +++ b/third-party/mbedtls-3.6/library/pem.c @@ -0,0 +1,520 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +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; + + /* Clean any remaining data previously written to the buffer */ + memset( buf + *olen, 0, buf_len - *olen ); + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ diff --git a/third-party/mbedtls-3.6/library/pk.c b/third-party/mbedtls-3.6/library/pk.c new file mode 100644 index 00000000..bf96debb --- /dev/null +++ b/third-party/mbedtls-3.6/library/pk.c @@ -0,0 +1,407 @@ +/* + * Public Key abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#include +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 */ diff --git a/third-party/mbedtls-3.6/library/pk_wrap.c b/third-party/mbedtls-3.6/library/pk_wrap.c new file mode 100644 index 00000000..966a17c1 --- /dev/null +++ b/third-party/mbedtls-3.6/library/pk_wrap.c @@ -0,0 +1,551 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk_internal.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#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 ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + 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 */ diff --git a/third-party/mbedtls-3.6/library/pkcs11.c b/third-party/mbedtls-3.6/library/pkcs11.c new file mode 100644 index 00000000..cf484b86 --- /dev/null +++ b/third-party/mbedtls-3.6/library/pkcs11.c @@ -0,0 +1,265 @@ +/** + * \file pkcs11.c + * + * \brief Wrapper for PKCS#11 library libpkcs11-helper + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#include "mbedtls/pkcs11.h" + +#if defined(MBEDTLS_PKCS11_C) + +#include "mbedtls/md.h" +#include "mbedtls/oid.h" +#include "mbedtls/x509_crt.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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) */ diff --git a/third-party/mbedtls-3.6/library/pkcs12.c b/third-party/mbedtls-3.6/library/pkcs12.c new file mode 100644 index 00000000..9ee63c2d --- /dev/null +++ b/third-party/mbedtls-3.6/library/pkcs12.c @@ -0,0 +1,394 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" + +#include + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +#if defined(MBEDTLS_ASN1_PARSE_C) + +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 ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + +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 */ diff --git a/third-party/mbedtls-3.6/library/pkcs5.c b/third-party/mbedtls-3.6/library/pkcs5.c new file mode 100644 index 00000000..7d392a64 --- /dev/null +++ b/third-party/mbedtls-3.6/library/pkcs5.c @@ -0,0 +1,446 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +/* 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; +} + +#if defined(MBEDTLS_ASN1_PARSE_C) +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 ); +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +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 = 0, 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 UINT_MAX > 0xFFFFFFFF + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + goto cleanup; + + 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 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + goto cleanup; + + // 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; + } + +cleanup: + /* Zeroise buffers to clear sensitive data from memory. */ + mbedtls_zeroize( work, MBEDTLS_MD_MAX_SIZE ); + mbedtls_zeroize( md1, MBEDTLS_MD_MAX_SIZE ); + + return( ret ); +} + +#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 */ diff --git a/third-party/mbedtls-3.6/library/pkparse.c b/third-party/mbedtls-3.6/library/pkparse.c new file mode 100644 index 00000000..f54ed546 --- /dev/null +++ b/third-party/mbedtls-3.6/library/pkparse.c @@ -0,0 +1,1485 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#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) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. + * + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). + * + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. + */ +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); + + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + return( 0 ); +} + +/* + * 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 = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import E */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) + goto cleanup; + + /* Import D */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) + goto cleanup; + + /* Import P */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import Q */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) + goto cleanup; + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existance of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 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 ); + } + } + + if( p != end ) + { + /* + * 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) 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 ); + mbedtls_pk_init( 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 ); + mbedtls_pk_init( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) == 0 ) + { + return( 0 ); + } + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ + + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + + 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_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + + /* 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 + */ + key = pem.buf; + keylen = pem.buflen; + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_PEM_PARSE_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_free( &pem ); +#endif + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/third-party/mbedtls-3.6/library/pkwrite.c b/third-party/mbedtls-3.6/library/pkwrite.c new file mode 100644 index 00000000..d54c74a3 --- /dev/null +++ b/third-party/mbedtls-3.6/library/pkwrite.c @@ -0,0 +1,567 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/bignum.h" +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_ECP_C) +/* 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; +} +#endif /* MBEDTLS_ECP_C */ + +#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 ); +} + +/* + * privateKey OCTET STRING -- always of length ceil(log2(n)/8) + */ +static int pk_write_ec_private( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t byte_length = ( ec->grp.pbits + 7 ) / 8; + unsigned char tmp[MBEDTLS_ECP_MAX_BYTES]; + + ret = mbedtls_mpi_write_binary( &ec->d, tmp, byte_length ); + if( ret != 0 ) + goto exit; + ret = mbedtls_asn1_write_octet_string( p, start, tmp, byte_length ); + +exit: + mbedtls_zeroize( tmp, byte_length ); + return( ret ); +} +#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 */ + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_private( &c, buf, ec ) ); + + /* 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 */ diff --git a/third-party/mbedtls-3.6/library/platform.c b/third-party/mbedtls-3.6/library/platform.c new file mode 100644 index 00000000..a9267b16 --- /dev/null +++ b/third-party/mbedtls-3.6/library/platform.c @@ -0,0 +1,370 @@ +/* + * Platform abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" + +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} +#endif + +/* The compile time configuration of memory allocation via the macros + * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime + * configuration via mbedtls_platform_set_calloc_free(). So, omit everything + * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ +#if defined(MBEDTLS_PLATFORM_MEMORY) && \ + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) + +#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 && + !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && + defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ + +#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 */ diff --git a/third-party/mbedtls-3.6/library/ripemd160.c b/third-party/mbedtls-3.6/library/ripemd160.c new file mode 100644 index 00000000..d89ed0a3 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ripemd160.c @@ -0,0 +1,587 @@ +/* + * RIPE MD-160 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + +#include "mbedtls/ripemd160.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +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] ) +{ + struct + { + uint32_t A, B, C, D, E, Ap, Bp, Cp, Dp, Ep, X[16]; + } local; + + GET_UINT32_LE( local.X[ 0], data, 0 ); + GET_UINT32_LE( local.X[ 1], data, 4 ); + GET_UINT32_LE( local.X[ 2], data, 8 ); + GET_UINT32_LE( local.X[ 3], data, 12 ); + GET_UINT32_LE( local.X[ 4], data, 16 ); + GET_UINT32_LE( local.X[ 5], data, 20 ); + GET_UINT32_LE( local.X[ 6], data, 24 ); + GET_UINT32_LE( local.X[ 7], data, 28 ); + GET_UINT32_LE( local.X[ 8], data, 32 ); + GET_UINT32_LE( local.X[ 9], data, 36 ); + GET_UINT32_LE( local.X[10], data, 40 ); + GET_UINT32_LE( local.X[11], data, 44 ); + GET_UINT32_LE( local.X[12], data, 48 ); + GET_UINT32_LE( local.X[13], data, 52 ); + GET_UINT32_LE( local.X[14], data, 56 ); + GET_UINT32_LE( local.X[15], data, 60 ); + + local.A = local.Ap = ctx->state[0]; + local.B = local.Bp = ctx->state[1]; + local.C = local.Cp = ctx->state[2]; + local.D = local.Dp = ctx->state[3]; + local.E = local.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 ) + local.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( local.A, local.B, local.C, local.D, local.E, 0, 11, 5, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 1, 14, 14, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 2, 15, 7, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 12, 0, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 4, 5, 9, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 5, 8, 2, 15 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 7, 11, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 7, 9, 4, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 11, 13, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 13, 6, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 14, 15, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 15, 8, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 12, 6, 1, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 7, 10, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 9, 3, 12 ); + P2( local.A, local.B, local.C, local.D, local.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( local.E, local.A, local.B, local.C, local.D, 7, 7, 6, 9 ); + P2( local.D, local.E, local.A, local.B, local.C, 4, 6, 11, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 13, 8, 3, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 13, 7, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 10, 11, 0, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 6, 9, 13, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 7, 5, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 3, 15, 10, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 7, 14, 7 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 12, 15, 7 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 15, 8, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 5, 9, 12, 7 ); + P2( local.C, local.D, local.E, local.A, local.B, 2, 11, 4, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 7, 9, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 13, 1, 13 ); + P2( local.E, local.A, local.B, local.C, local.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( local.D, local.E, local.A, local.B, local.C, 3, 11, 15, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 10, 13, 5, 7 ); + P2( local.B, local.C, local.D, local.E, local.A, 14, 6, 1, 15 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 7, 3, 11 ); + P2( local.E, local.A, local.B, local.C, local.D, 9, 14, 7, 8 ); + P2( local.D, local.E, local.A, local.B, local.C, 15, 9, 14, 6 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 13, 6, 6 ); + P2( local.B, local.C, local.D, local.E, local.A, 1, 15, 9, 14 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 14, 11, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 7, 8, 8, 13 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 13, 12, 5 ); + P2( local.C, local.D, local.E, local.A, local.B, 6, 6, 2, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 5, 10, 13 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 12, 0, 13 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 7, 4, 7 ); + P2( local.D, local.E, local.A, local.B, local.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( local.C, local.D, local.E, local.A, local.B, 1, 11, 8, 15 ); + P2( local.B, local.C, local.D, local.E, local.A, 9, 12, 6, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 11, 14, 4, 8 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 15, 1, 11 ); + P2( local.D, local.E, local.A, local.B, local.C, 0, 14, 3, 14 ); + P2( local.C, local.D, local.E, local.A, local.B, 8, 15, 11, 14 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 9, 15, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 4, 8, 0, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 13, 9, 5, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 3, 14, 12, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 5, 2, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 15, 6, 13, 9 ); + P2( local.A, local.B, local.C, local.D, local.E, 14, 8, 9, 12 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 6, 7, 5 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 5, 10, 15 ); + P2( local.C, local.D, local.E, local.A, local.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( local.B, local.C, local.D, local.E, local.A, 4, 9, 12, 8 ); + P2( local.A, local.B, local.C, local.D, local.E, 0, 15, 15, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 5, 5, 10, 12 ); + P2( local.D, local.E, local.A, local.B, local.C, 9, 11, 4, 9 ); + P2( local.C, local.D, local.E, local.A, local.B, 7, 6, 1, 12 ); + P2( local.B, local.C, local.D, local.E, local.A, 12, 8, 5, 5 ); + P2( local.A, local.B, local.C, local.D, local.E, 2, 13, 8, 14 ); + P2( local.E, local.A, local.B, local.C, local.D, 10, 12, 7, 6 ); + P2( local.D, local.E, local.A, local.B, local.C, 14, 5, 6, 8 ); + P2( local.C, local.D, local.E, local.A, local.B, 1, 12, 2, 13 ); + P2( local.B, local.C, local.D, local.E, local.A, 3, 13, 13, 6 ); + P2( local.A, local.B, local.C, local.D, local.E, 8, 14, 14, 5 ); + P2( local.E, local.A, local.B, local.C, local.D, 11, 11, 0, 15 ); + P2( local.D, local.E, local.A, local.B, local.C, 6, 8, 3, 13 ); + P2( local.C, local.D, local.E, local.A, local.B, 15, 5, 9, 11 ); + P2( local.B, local.C, local.D, local.E, local.A, 13, 6, 11, 11 ); +#undef F +#undef K +#undef Fp +#undef Kp + + local.C = ctx->state[1] + local.C + local.Dp; + ctx->state[1] = ctx->state[2] + local.D + local.Ep; + ctx->state[2] = ctx->state[3] + local.E + local.Ap; + ctx->state[3] = ctx->state[4] + local.A + local.Bp; + ctx->state[4] = ctx->state[0] + local.B + local.Cp; + ctx->state[0] = local.C; + + /* Zeroise variables to clear sensitive data from memory. */ + mbedtls_zeroize( &local, sizeof( local ) ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/rsa.c b/third-party/mbedtls-3.6/library/rsa.c new file mode 100644 index 00000000..94ace5e2 --- /dev/null +++ b/third-party/mbedtls-3.6/library/rsa.c @@ -0,0 +1,2602 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + +#if defined(MBEDTLS_PKCS1_V15) +/* 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 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +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 ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + const int have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + const int have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + const int have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif + + /* + * 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 && ! ( have_DP && have_DQ && have_QP ) ) + { + 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) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; + 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; + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + + if( f_rng == NULL || nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + /* + * 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 ); + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret; + return( 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; + mbedtls_mpi R; + + mbedtls_mpi_init( &R ); + + 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 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + 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 && ret >= -0x007f ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( ret ); +} + +#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) +/** Turn zero-or-nonzero into zero-or-all-bits-one, without branches. + * + * \param value The value to analyze. + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +static unsigned all_or_nothing_int( unsigned value ) +{ + /* 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 + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} + +/** Check whether a size is out of bounds, without branches. + * + * This is equivalent to `size > max`, but is likely to be compiled to + * to code using bitwise operation rather than a branch. + * + * \param size Size to check. + * \param max Maximum desired value for \p size. + * \return \c 0 if `size <= max`. + * \return \c 1 if `size > max`. + */ +static unsigned size_greater_than( size_t size, size_t max ) +{ + /* Return the sign bit (1 for negative) of (max - size). */ + return( ( max - size ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} + +/** Choose between two integer values, without branches. + * + * This is equivalent to `cond ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param cond Condition to test. + * \param if1 Value to use if \p cond is nonzero. + * \param if0 Value to use if \p cond is zero. + * \return \c if1 if \p cond is nonzero, otherwise \c if0. + */ +static unsigned if_int( unsigned cond, unsigned if1, unsigned if0 ) +{ + unsigned mask = all_or_nothing_int( cond ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} + +/** Shift some data towards the left inside a buffer without leaking + * the length of the data through side channels. + * + * `mem_move_to_left(start, total, offset)` is functionally equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = size_greater_than( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = if_int( no_op, current, next ); + } + buf[total-1] = if_int( no_op, buf[total-1], 0 ); + } +} + +/* + * 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 = ctx->len; + size_t i; + size_t plaintext_max_size = ( output_max_len > ilen - 11 ? + ilen - 11 : + output_max_len ); + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + 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; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= buf[0]; + + if( mode == MBEDTLS_RSA_PRIVATE ) + { + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= buf[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + } + else + { + /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00 + * where PS must be at least 8 bytes with the value 0xFF. */ + bad |= buf[1] ^ MBEDTLS_RSA_SIGN; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. + * If there's a non-0xff byte in the padding, the padding is bad. */ + for( i = 2; i < ilen; i++ ) + { + pad_done |= if_int( buf[i], 0, 1 ); + pad_count += if_int( pad_done, 0, 1 ); + bad |= if_int( pad_done, 0, buf[i] ^ 0xFF ); + } + } + + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= if_int( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= size_greater_than( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = if_int( bad, + (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = size_greater_than( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) if_int( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + if_int( output_too_large, - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = all_or_nothing_int( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + buf[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = if_int( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mem_move_to_left( buf + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros + * into the output buffer. */ + memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + +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->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) + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * 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__) && !defined(__NetBSD__) + 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 && !NetBSD */ + + 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 */ diff --git a/third-party/mbedtls-3.6/library/rsa_internal.c b/third-party/mbedtls-3.6/library/rsa_internal.c new file mode 100644 index 00000000..30115a0d --- /dev/null +++ b/third-party/mbedtls-3.6/library/rsa_internal.c @@ -0,0 +1,512 @@ +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * 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 */ diff --git a/third-party/mbedtls-3.6/library/sha1.c b/third-party/mbedtls-3.6/library/sha1.c new file mode 100644 index 00000000..7e6981d5 --- /dev/null +++ b/third-party/mbedtls-3.6/library/sha1.c @@ -0,0 +1,584 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA1_C) + +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +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 (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] ) +{ + struct + { + uint32_t temp, W[16], A, B, C, D, E; + } local; + + GET_UINT32_BE( local.W[ 0], data, 0 ); + GET_UINT32_BE( local.W[ 1], data, 4 ); + GET_UINT32_BE( local.W[ 2], data, 8 ); + GET_UINT32_BE( local.W[ 3], data, 12 ); + GET_UINT32_BE( local.W[ 4], data, 16 ); + GET_UINT32_BE( local.W[ 5], data, 20 ); + GET_UINT32_BE( local.W[ 6], data, 24 ); + GET_UINT32_BE( local.W[ 7], data, 28 ); + GET_UINT32_BE( local.W[ 8], data, 32 ); + GET_UINT32_BE( local.W[ 9], data, 36 ); + GET_UINT32_BE( local.W[10], data, 40 ); + GET_UINT32_BE( local.W[11], data, 44 ); + GET_UINT32_BE( local.W[12], data, 48 ); + GET_UINT32_BE( local.W[13], data, 52 ); + GET_UINT32_BE( local.W[14], data, 56 ); + GET_UINT32_BE( local.W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + local.temp = local.W[( t - 3 ) & 0x0F] ^ \ + local.W[( t - 8 ) & 0x0F] ^ \ + local.W[( t - 14 ) & 0x0F] ^ \ + local.W[ t & 0x0F], \ + ( local.W[t & 0x0F] = S(local.temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( local.A, local.B, local.C, local.D, local.E, local.W[0] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[1] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[2] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[3] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[4] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[5] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[6] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[7] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[8] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[9] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[10] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[11] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[12] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[13] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[14] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[15] ); + P( local.E, local.A, local.B, local.C, local.D, R(16) ); + P( local.D, local.E, local.A, local.B, local.C, R(17) ); + P( local.C, local.D, local.E, local.A, local.B, R(18) ); + P( local.B, local.C, local.D, local.E, local.A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( local.A, local.B, local.C, local.D, local.E, R(20) ); + P( local.E, local.A, local.B, local.C, local.D, R(21) ); + P( local.D, local.E, local.A, local.B, local.C, R(22) ); + P( local.C, local.D, local.E, local.A, local.B, R(23) ); + P( local.B, local.C, local.D, local.E, local.A, R(24) ); + P( local.A, local.B, local.C, local.D, local.E, R(25) ); + P( local.E, local.A, local.B, local.C, local.D, R(26) ); + P( local.D, local.E, local.A, local.B, local.C, R(27) ); + P( local.C, local.D, local.E, local.A, local.B, R(28) ); + P( local.B, local.C, local.D, local.E, local.A, R(29) ); + P( local.A, local.B, local.C, local.D, local.E, R(30) ); + P( local.E, local.A, local.B, local.C, local.D, R(31) ); + P( local.D, local.E, local.A, local.B, local.C, R(32) ); + P( local.C, local.D, local.E, local.A, local.B, R(33) ); + P( local.B, local.C, local.D, local.E, local.A, R(34) ); + P( local.A, local.B, local.C, local.D, local.E, R(35) ); + P( local.E, local.A, local.B, local.C, local.D, R(36) ); + P( local.D, local.E, local.A, local.B, local.C, R(37) ); + P( local.C, local.D, local.E, local.A, local.B, R(38) ); + P( local.B, local.C, local.D, local.E, local.A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( local.A, local.B, local.C, local.D, local.E, R(40) ); + P( local.E, local.A, local.B, local.C, local.D, R(41) ); + P( local.D, local.E, local.A, local.B, local.C, R(42) ); + P( local.C, local.D, local.E, local.A, local.B, R(43) ); + P( local.B, local.C, local.D, local.E, local.A, R(44) ); + P( local.A, local.B, local.C, local.D, local.E, R(45) ); + P( local.E, local.A, local.B, local.C, local.D, R(46) ); + P( local.D, local.E, local.A, local.B, local.C, R(47) ); + P( local.C, local.D, local.E, local.A, local.B, R(48) ); + P( local.B, local.C, local.D, local.E, local.A, R(49) ); + P( local.A, local.B, local.C, local.D, local.E, R(50) ); + P( local.E, local.A, local.B, local.C, local.D, R(51) ); + P( local.D, local.E, local.A, local.B, local.C, R(52) ); + P( local.C, local.D, local.E, local.A, local.B, R(53) ); + P( local.B, local.C, local.D, local.E, local.A, R(54) ); + P( local.A, local.B, local.C, local.D, local.E, R(55) ); + P( local.E, local.A, local.B, local.C, local.D, R(56) ); + P( local.D, local.E, local.A, local.B, local.C, R(57) ); + P( local.C, local.D, local.E, local.A, local.B, R(58) ); + P( local.B, local.C, local.D, local.E, local.A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( local.A, local.B, local.C, local.D, local.E, R(60) ); + P( local.E, local.A, local.B, local.C, local.D, R(61) ); + P( local.D, local.E, local.A, local.B, local.C, R(62) ); + P( local.C, local.D, local.E, local.A, local.B, R(63) ); + P( local.B, local.C, local.D, local.E, local.A, R(64) ); + P( local.A, local.B, local.C, local.D, local.E, R(65) ); + P( local.E, local.A, local.B, local.C, local.D, R(66) ); + P( local.D, local.E, local.A, local.B, local.C, R(67) ); + P( local.C, local.D, local.E, local.A, local.B, R(68) ); + P( local.B, local.C, local.D, local.E, local.A, R(69) ); + P( local.A, local.B, local.C, local.D, local.E, R(70) ); + P( local.E, local.A, local.B, local.C, local.D, R(71) ); + P( local.D, local.E, local.A, local.B, local.C, R(72) ); + P( local.C, local.D, local.E, local.A, local.B, R(73) ); + P( local.B, local.C, local.D, local.E, local.A, R(74) ); + P( local.A, local.B, local.C, local.D, local.E, R(75) ); + P( local.E, local.A, local.B, local.C, local.D, R(76) ); + P( local.D, local.E, local.A, local.B, local.C, R(77) ); + P( local.C, local.D, local.E, local.A, local.B, R(78) ); + P( local.B, local.C, local.D, local.E, local.A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_zeroize( &local, sizeof( local ) ); + + 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 + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + 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 */ diff --git a/third-party/mbedtls-3.6/library/sha256.c b/third-party/mbedtls-3.6/library/sha256.c new file mode 100644 index 00000000..9bbf6907 --- /dev/null +++ b/third-party/mbedtls-3.6/library/sha256.c @@ -0,0 +1,616 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA256_C) + +#include "mbedtls/sha256.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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) \ +( \ + local.W[t] = S1(local.W[t - 2]) + local.W[t - 7] + \ + S0(local.W[t - 15]) + local.W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + local.temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + local.temp2 = S2(a) + F0(a,b,c); \ + d += local.temp1; h = local.temp1 + local.temp2; \ +} + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + } local; + + unsigned int i; + + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( local.W[i], data, 4 * i ); + else + R( i ); + + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); + + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( local.W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], R(i+0), K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], R(i+1), K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], R(i+2), K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], R(i+3), K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], R(i+4), K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], R(i+5), K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], R(i+6), K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_zeroize( &local, sizeof( local ) ); + + 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 + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + 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 */ diff --git a/third-party/mbedtls-3.6/library/sha512.c b/third-party/mbedtls-3.6/library/sha512.c new file mode 100644 index 00000000..fdd4ec9d --- /dev/null +++ b/third-party/mbedtls-3.6/library/sha512.c @@ -0,0 +1,653 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SHA512_C) + +#include "mbedtls/sha512.h" + +#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) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 + */ +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; + struct + { + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + } local; + +#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) \ +{ \ + local.temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + local.temp2 = S2(a) + F0(a,b,c); \ + d += local.temp1; h = local.temp1 + local.temp2; \ +} + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( local.W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + local.F = ctx->state[5]; + local.G = ctx->state[6]; + local.H = ctx->state[7]; + i = 0; + + do + { + P( local.A, local.B, local.C, local.D, local.E, + local.F, local.G, local.H, local.W[i], K[i] ); i++; + P( local.H, local.A, local.B, local.C, local.D, + local.E, local.F, local.G, local.W[i], K[i] ); i++; + P( local.G, local.H, local.A, local.B, local.C, + local.D, local.E, local.F, local.W[i], K[i] ); i++; + P( local.F, local.G, local.H, local.A, local.B, + local.C, local.D, local.E, local.W[i], K[i] ); i++; + P( local.E, local.F, local.G, local.H, local.A, + local.B, local.C, local.D, local.W[i], K[i] ); i++; + P( local.D, local.E, local.F, local.G, local.H, + local.A, local.B, local.C, local.W[i], K[i] ); i++; + P( local.C, local.D, local.E, local.F, local.G, + local.H, local.A, local.B, local.W[i], K[i] ); i++; + P( local.B, local.C, local.D, local.E, local.F, + local.G, local.H, local.A, local.W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + ctx->state[5] += local.F; + ctx->state[6] += local.G; + ctx->state[7] += local.H; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_zeroize( &local, sizeof( local ) ); + + 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 + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret; + unsigned used; + uint64_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, ctx->buffer, 112 ); + PUT_UINT64_BE( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + 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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_cache.c b/third-party/mbedtls-3.6/library/ssl_cache.c new file mode 100644 index 00000000..1d2558a1 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_cache.c @@ -0,0 +1,352 @@ +/* + * SSL session cache implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cache.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_ciphersuites.c b/third-party/mbedtls-3.6/library/ssl_ciphersuites.c new file mode 100644 index 00000000..7efc558d --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_ciphersuites.c @@ -0,0 +1,1915 @@ +/** + * \file ssl_ciphersuites.c + * + * \brief SSL ciphersuites for mbed TLS + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#endif + +#include "mbedtls/ssl_ciphersuites.h" +#include "mbedtls/ssl.h" + +#include + +/* + * Ordered from most preferred to least preferred in terms of security. + * + * Current rule (except RC4 and 3DES, 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 + * 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, + + /* 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, + + /* 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, + + /* 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, + + /* 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, + + /* 3DES 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, + 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_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + 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; + +static int ciphersuite_is_removed( const mbedtls_ssl_ciphersuite_t *cs_info ) +{ + (void)cs_info; + +#if defined(MBEDTLS_REMOVE_ARC4_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif /* MBEDTLS_REMOVE_ARC4_CIPHERSUITES */ + +#if defined(MBEDTLS_REMOVE_3DES_CIPHERSUITES) + if( cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_ECB || + cs_info->cipher == MBEDTLS_CIPHER_DES_EDE3_CBC ) + { + return( 1 ); + } +#endif /* MBEDTLS_REMOVE_3DES_CIPHERSUITES */ + + return( 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++ ) + { + const mbedtls_ssl_ciphersuite_t *cs_info; + if( ( cs_info = mbedtls_ssl_ciphersuite_from_id( *p ) ) != NULL && + !ciphersuite_is_removed( cs_info ) ) + { + *(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) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +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: + case MBEDTLS_KEY_EXCHANGE_ECJPAKE: + return( 1 ); + + default: + return( 0 ); + } +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/ + +#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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_cli.c b/third-party/mbedtls-3.6/library/ssl_cli.c new file mode 100644 index 00000000..8a485707 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_cli.c @@ -0,0 +1,3801 @@ +/* + * SSLv3/TLSv1 client-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_CLI_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#include + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) +static int ssl_write_hostname_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t hostname_len; + + *olen = 0; + + if( ssl->hostname == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding server name extension: %s", + ssl->hostname ) ); + + hostname_len = strlen( ssl->hostname ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, hostname_len + 9 ); + + /* + * 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; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +static int ssl_write_renegotiation_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *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( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding renegotiation extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 + ssl->verify_data_len ); + + /* + * 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; + + return( 0 ); +} +#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 int ssl_write_signature_algorithms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + 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( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding signature_algorithms extension" ) ); + + if( ssl->conf->sig_hashes == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + 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( sig_alg_len > MBEDTLS_SSL_MAX_SIG_HASH_ALG_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "length in bytes of sig-hash-alg extension too big" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty signature algorithms list, this is a configuration error. */ + if( sig_alg_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, sig_alg_len + 6 ); + + /* + * 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; + + 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_write_supported_elliptic_curves_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + unsigned char *elliptic_curve_list = p + 6; + size_t elliptic_curve_len = 0; + const mbedtls_ecp_curve_info *info; + const mbedtls_ecp_group_id *grp_id; + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_elliptic_curves extension" ) ); + + if( ssl->conf->curve_list == NULL ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + if( info == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "invalid curve in ssl configuration" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + elliptic_curve_len += 2; + + if( elliptic_curve_len > MBEDTLS_SSL_MAX_CURVE_LIST_LEN ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "malformed supported_elliptic_curves extension in config" ) ); + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + } + } + + /* Empty elliptic curve list, this is a configuration error. */ + if( elliptic_curve_len == 0 ) + return( MBEDTLS_ERR_SSL_BAD_CONFIG ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + elliptic_curve_len ); + + elliptic_curve_len = 0; + + for( grp_id = ssl->conf->curve_list; + *grp_id != MBEDTLS_ECP_DP_NONE; + grp_id++ ) + { + info = mbedtls_ecp_curve_info_from_grp_id( *grp_id ); + elliptic_curve_list[elliptic_curve_len++] = info->tls_id >> 8; + elliptic_curve_list[elliptic_curve_len++] = info->tls_id & 0xFF; + } + + *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; + + return( 0 ); +} + +static int ssl_write_supported_point_formats_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + (void) ssl; /* ssl used for debugging only */ + + *olen = 0; + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding supported_point_formats extension" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 ); + + *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; + + return( 0 ); +} +#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || + MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +static int ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + int ret; + unsigned char *p = buf; + 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( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding ecjpake_kkpp extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *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( ret ); + } + + ssl->handshake->ecjpake_cache = mbedtls_calloc( 1, kkpp_len ); + if( ssl->handshake->ecjpake_cache == NULL ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "allocation failed" ) ); + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + 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; + MBEDTLS_SSL_CHK_BUF_PTR( p + 2, end, kkpp_len ); + + 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; + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +static int ssl_write_max_fragment_length_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->mfl_code == MBEDTLS_SSL_MAX_FRAG_LEN_NONE ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding max_fragment_length extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 5 ); + + *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; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +static int ssl_write_truncated_hmac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->trunc_hmac == MBEDTLS_SSL_TRUNC_HMAC_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding truncated_hmac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *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; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +static int ssl_write_encrypt_then_mac_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding encrypt_then_mac extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *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; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +static int ssl_write_extended_ms_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + + *olen = 0; + + if( ssl->conf->extended_ms == MBEDTLS_SSL_EXTENDED_MS_DISABLED || + ssl->conf->max_minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding extended_master_secret extension" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 ); + + *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; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +static int ssl_write_session_ticket_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t tlen = ssl->session_negotiate->ticket_len; + + *olen = 0; + + if( ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "client hello, adding session ticket extension" ) ); + + /* The addition is safe here since the ticket length is 16 bit. */ + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 4 + tlen ); + + *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( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "sending session ticket of length %d", tlen ) ); + + memcpy( p, ssl->session_negotiate->ticket, tlen ); + + *olen += tlen; + + return( 0 ); +} +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_ALPN) +static int ssl_write_alpn_ext( mbedtls_ssl_context *ssl, + unsigned char *buf, + const unsigned char *end, + size_t *olen ) +{ + unsigned char *p = buf; + size_t alpnlen = 0; + const char **cur; + + *olen = 0; + + if( ssl->conf->alpn_list == NULL ) + return( 0 ); + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, adding alpn extension" ) ); + + for( cur = ssl->conf->alpn_list; *cur != NULL; cur++ ) + alpnlen += strlen( *cur ) + 1; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 6 + alpnlen ); + + *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++ ) + { + /* + * mbedtls_ssl_conf_set_alpn_protocols() checked that the length of + * protocol names is less than 255. + */ + *p = (unsigned char)strlen( *cur ); + 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 ); + + return( 0 ); +} +#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 ); +} + +/** + * \brief Validate cipher suite against config in SSL context. + * + * \param suite_info cipher suite to validate + * \param ssl SSL context + * \param min_minor_ver Minimal minor version to accept a cipher suite + * \param max_minor_ver Maximal minor version to accept a cipher suite + * + * \return 0 if valid, else 1 + */ +static int ssl_validate_ciphersuite( + const mbedtls_ssl_ciphersuite_t * suite_info, + const mbedtls_ssl_context * ssl, + int min_minor_ver, int max_minor_ver ) +{ + (void) ssl; + if( suite_info == NULL ) + return( 1 ); + + if( suite_info->min_minor_ver > max_minor_ver || + suite_info->max_minor_ver < min_minor_ver ) + return( 1 ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + ( suite_info->flags & MBEDTLS_CIPHERSUITE_NODTLS ) ) + return( 1 ); +#endif + +#if defined(MBEDTLS_ARC4_C) + if( ssl->conf->arc4_disabled == MBEDTLS_SSL_ARC4_DISABLED && + suite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + return( 1 ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE && + mbedtls_ecjpake_check( &ssl->handshake->ecjpake_ctx ) != 0 ) + return( 1 ); +#endif + + 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; + const unsigned char *end; + + unsigned char offer_compress; + const int *ciphersuites; + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + int uses_ec = 0; +#endif + + 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 ); + } + + buf = ssl->out_msg; + end = buf + MBEDTLS_SSL_MAX_CONTENT_LEN; + + /* + * Check if there's enough space for the first part of the ClientHello + * consisting of the 38 bytes described below, the session identifier (at + * most 32 bytes) and its length (1 byte). + * + * Use static upper bounds instead of the actual values + * to allow the compiler to optimize this away. + */ + MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 ); + + /* + * The 38 first bytes of the ClientHello: + * 0 . 0 handshake type (written later) + * 1 . 3 handshake length (written later) + * 4 . 5 highest version supported + * 6 . 9 current UNIX time + * 10 . 37 random bytes + * + * The current UNIX time (4 bytes) and following 28 random bytes are written + * by ssl_generate_random() into ssl->handshake->randbytes buffer and then + * copied from there into the output buffer. + */ + + 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 . .. DTLS 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 */ + + /* + * The first check of the output buffer size above ( + * MBEDTLS_SSL_CHK_BUF_PTR( buf, end, 38 + 1 + 32 );) + * has checked that there is enough space in the output buffer for the + * session identifier length byte and the session identifier (n <= 32). + */ + *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 ); + + /* + * With 'n' being the length of the session identifier + * + * 39+n . 39+n DTLS only: cookie length (1 byte) + * 40+n . .. DTLS only: cookie + * .. . .. ciphersuitelist length (2 bytes) + * .. . .. ciphersuitelist + * .. . .. compression methods length (1 byte) + * .. . .. compression methods + * .. . .. extensions length (2 bytes) + * .. . .. extensions + */ + + /* + * DTLS cookie + */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 1 ); + + 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; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, + 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; + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + p += 2; + + for( i = 0; ciphersuites[i] != 0; i++ ) + { + ciphersuite_info = mbedtls_ssl_ciphersuite_from_id( ciphersuites[i] ); + + if( ssl_validate_ciphersuite( ciphersuite_info, ssl, + ssl->conf->min_minor_ver, + ssl->conf->max_minor_ver ) != 0 ) + continue; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "client hello, add ciphersuite: %04x", + ciphersuites[i] ) ); + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + uses_ec |= mbedtls_ssl_ciphersuite_uses_ec( ciphersuite_info ); +#endif + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + + 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" ) ); + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *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" ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *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: if 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 ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 3 ); + *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 ) ); + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + *p++ = 1; + *p++ = MBEDTLS_SSL_COMPRESS_NULL; + } + + /* First write extensions, then the total length */ + + MBEDTLS_SSL_CHK_BUF_PTR( p, end, 2 ); + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ( ret = ssl_write_hostname_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_hostname_ext", ret ); + return( ret ); + } + 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) + if( ( ret = ssl_write_renegotiation_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_renegotiation_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) + if( ( ret = ssl_write_signature_algorithms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_signature_algorithms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( uses_ec ) + { + if( ( ret = ssl_write_supported_elliptic_curves_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_elliptic_curves_ext", ret ); + return( ret ); + } + ext_len += olen; + + if( ( ret = ssl_write_supported_point_formats_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_supported_point_formats_ext", ret ); + return( ret ); + } + ext_len += olen; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( ( ret = ssl_write_ecjpake_kkpp_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_ecjpake_kkpp_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = ssl_write_max_fragment_length_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_max_fragment_length_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( ( ret = ssl_write_truncated_hmac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_truncated_hmac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( ( ret = ssl_write_encrypt_then_mac_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_encrypt_then_mac_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( ( ret = ssl_write_extended_ms_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_extended_ms_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( ( ret = ssl_write_alpn_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_alpn_ext", ret ); + return( ret ); + } + ext_len += olen; +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( ( ret = ssl_write_session_ticket_ext( ssl, p + 2 + ext_len, + end, &olen ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "ssl_write_session_ticket_ext", ret ); + return( ret ); + } + 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 ) + { + /* No need to check for space here, because the extension + * writing functions already took care of that. */ + *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 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 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 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 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 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 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; + + if( len == 0 || (size_t)( buf[0] + 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 ); + } + list_size = buf[0]; + + 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 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" ) ); + + /* Check that there is enough room for: + * - 2 bytes of version + * - 1 byte of cookie_len + */ + if( mbedtls_ssl_hs_hdr_len( ssl ) + 3 > ssl->in_msglen ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "incoming HelloVerifyRequest message is too short" ) ); + 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 ); + } + + /* + * 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++; + 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_SSL_DEBUG_BUF( 3, "cookie", p, cookie_len ); + + 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 renegotiation" ) ); + + 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] ) ); + + /* + * Perform cipher suite validation in same way as in ssl_write_client_hello. + */ + 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; + } + } + + suite_info = mbedtls_ssl_ciphersuite_from_id( + ssl->session_negotiate->ciphersuite ); + if( ssl_validate_ciphersuite( suite_info, ssl, ssl->minor_ver, + ssl->minor_ver ) != 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 ); + } + + MBEDTLS_SSL_DEBUG_MSG( 3, + ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); + + 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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( end - (*p) < 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( end - (*p) < (int) 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 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 = ssl_get_ecdh_params_from_cert( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "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 */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) ) + { + 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 ); + } + cert_type_len = buf[mbedtls_ssl_hs_hdr_len( ssl )]; + n = cert_type_len; + + /* + * In the subsequent code there are two paths that read from buf: + * * the length of the signature algorithms field (if minor version of + * SSL is 3), + * * distinguished name length otherwise. + * Both reach at most the index: + * ...hdr_len + 2 + n, + * therefore the buffer length at this point must be greater than that + * regardless of the actual code path. + */ + 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; + size_t i; +#endif + + /* + * The furthest access in buf is in the loop few lines below: + * sig_alg[i + 1], + * where: + * sig_alg = buf + ...hdr_len + 3 + n, + * max(i) = sig_alg_len - 1. + * Therefore the furthest access is: + * buf[...hdr_len + 3 + n + sig_alg_len - 1 + 1], + * which reduces to: + * buf[...hdr_len + 3 + n + sig_alg_len], + * which is one less than we need the buf to be. + */ + if( ssl->in_hslen <= mbedtls_ssl_hs_hdr_len( ssl ) + + 3 + n + sig_alg_len ) + { + 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 ); + } + +#if defined(MBEDTLS_DEBUG_C) + sig_alg = buf + mbedtls_ssl_hs_hdr_len( ssl ) + 3 + n; + 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; + } +#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 = ( ((uint32_t) 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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_cookie.c b/third-party/mbedtls-3.6/library/ssl_cookie.c new file mode 100644 index 00000000..a777a93f --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_cookie.c @@ -0,0 +1,283 @@ +/* + * DTLS cookie callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * These session callbacks use a simple chained list + * to store and retrieve the session information. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_cookie.h" +#include "mbedtls/ssl_internal.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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]; + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_HMAC_LEN ); + + 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 ); + + MBEDTLS_SSL_CHK_BUF_PTR( *p, end, COOKIE_LEN ); + +#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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_srv.c b/third-party/mbedtls-3.6/library/ssl_srv.c new file mode 100644 index 00000000..c3e89486 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_srv.c @@ -0,0 +1,4160 @@ +/* + * SSLv3/TLSv1 server-side functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_SRV_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} +#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" ) ); + + if( len < 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 ); + } + 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 > 2 ) + { + 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; + + if ( len < 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 ); + } + 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; + + if ( len < 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 ); + } + 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; + + if( len == 0 || (size_t)( buf[0] + 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 ); + } + list_size = buf[0]; + + 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 omitted) 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; + unsigned int ext_size; + if ( 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 ); + } + ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) ); + 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) + if ( mbedtls_ssl_ciphersuite_uses_ec( + mbedtls_ssl_ciphersuite_from_id( ssl->session_negotiate->ciphersuite ) ) ) + { + 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 = 0; +#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 + 2 > end ) { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) ); + return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); + } + 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 ); + + /* In case of a failure in decryption, peer_pmslen may not have been + * initialized, and it is accessed later. The diff will be nonzero anyway, + * but it's better to avoid accessing uninitialized memory in any case. + */ + peer_pmslen = 0; + + 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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_ticket.c b/third-party/mbedtls-3.6/library/ssl_ticket.c new file mode 100644 index 00000000..ad0f11f2 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_ticket.c @@ -0,0 +1,534 @@ +/* + * TLS server tickets callbacks implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ssl_internal.h" +#include "mbedtls/ssl_ticket.h" + +#include + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 */ + +#define TICKET_KEY_NAME_BYTES 4 +#define TICKET_IV_BYTES 12 +#define TICKET_CRYPT_LEN_BYTES 2 +#define TICKET_AUTH_TAG_BYTES 16 + +#define TICKET_MIN_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES + \ + TICKET_AUTH_TAG_BYTES ) +#define TICKET_ADD_DATA_LEN ( TICKET_KEY_NAME_BYTES + \ + TICKET_IV_BYTES + \ + TICKET_CRYPT_LEN_BYTES ) + +/* + * 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( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) + 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( 3 > (size_t)( end - p ) ) + 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( cert_len > (size_t)( end - p ) ) + 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 + TICKET_KEY_NAME_BYTES; + unsigned char *state_len_bytes = iv + TICKET_IV_BYTES; + unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; + 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. */ + MBEDTLS_SSL_CHK_BUF_PTR( start, end, TICKET_MIN_LEN ); + +#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, TICKET_KEY_NAME_BYTES ); + + if( ( ret = ctx->f_rng( ctx->p_rng, iv, TICKET_IV_BYTES ) ) != 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, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, state, &ciph_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 0 ) + { + goto cleanup; + } + if( ciph_len != clear_len ) + { + ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; + goto cleanup; + } + + *tlen = TICKET_MIN_LEN + 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 + TICKET_KEY_NAME_BYTES; + unsigned char *enc_len_p = iv + TICKET_IV_BYTES; + unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; + unsigned char *tag; + size_t enc_len, clear_len; + + if( ctx == NULL || ctx->f_rng == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( len < TICKET_MIN_LEN ) + 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 != TICKET_MIN_LEN + enc_len ) + { + 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, TICKET_IV_BYTES, + /* Additional data: key name, IV and length */ + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len, + ticket, &clear_len, + tag, TICKET_AUTH_TAG_BYTES ) ) != 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 */ diff --git a/third-party/mbedtls-3.6/library/ssl_tls.c b/third-party/mbedtls-3.6/library/ssl_tls.c new file mode 100644 index 00000000..2b1aa011 --- /dev/null +++ b/third-party/mbedtls-3.6/library/ssl_tls.c @@ -0,0 +1,8604 @@ +/* + * SSLv3/TLSv1 shared functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/debug.h" +#include "mbedtls/ssl.h" +#include "mbedtls/ssl_internal.h" + +#include + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#include "mbedtls/oid.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* 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 ) + { + /* For HMAC-based ciphersuites, initialize the HMAC transforms. + For AEAD-based ciphersuites, there is nothing to do here. */ + if( mac_key_len != 0 ) + { + 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 ) + { + 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 ) +{ + 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 ) +{ + 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 ) +{ + 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 ) +{ + 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 + */ + if( end - p < 2 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + *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_SSL_SOME_SUITES_USE_CBC) +#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_SSL_SOME_SUITES_USE_CBC) + 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 ) + { + unsigned char mac[MBEDTLS_SSL_MAC_ADD]; + + /* + * 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, mac ); + mbedtls_md_hmac_reset( &ssl->transform_out->md_ctx_enc ); + + memcpy( ssl->out_iv + ssl->out_msglen, mac, + ssl->transform_out->maclen ); + + ssl->out_msglen += ssl->transform_out->maclen; + auth_done++; + } +#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */ + } + else +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC */ + { + 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 ); +} + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) +/* + * Constant-flow conditional memcpy: + * - if c1 == c2, equivalent to memcpy(dst, src, len), + * - otherwise, a no-op, + * but with execution flow independent of the values of c1 and c2. + * + * Use only bit operations to avoid branches that could be used by some + * compilers on some platforms to translate comparison operators. + */ +static void mbedtls_ssl_cf_memcpy_if_eq( unsigned char *dst, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ) +{ + /* diff = 0 if c1 == c2, non-zero otherwise */ + const size_t diff = c1 ^ c2; + + /* MSVC has a warning about unary minus on unsigned integer types, + * 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 + + /* diff_msb's most significant bit is equal to c1 != c2 */ + const size_t diff_msb = ( diff | -diff ); + + /* diff1 = c1 != c2 */ + const size_t diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); + + /* mask = c1 != c2 ? 0xff : 0x00 */ + const unsigned char mask = (unsigned char) -diff1; + +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + /* dst[i] = c1 != c2 ? dst[i] : src[i] */ + size_t i; + for( i = 0; i < len; i++ ) + dst[i] = ( dst[i] & mask ) | ( src[i] & ~mask ); +} + +/* + * Compute HMAC of variable-length data with constant flow. + * + * Only works with MD-5, SHA-1, SHA-256 and SHA-384. + * (Otherwise, computation of block_size needs to be adapted.) + */ +int mbedtls_ssl_cf_hmac( + mbedtls_md_context_t *ctx, + const unsigned char *add_data, size_t add_data_len, + const unsigned char *data, size_t data_len_secret, + size_t min_data_len, size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.0-1.2 only support SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ssl_cf_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } + + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); + + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); + +#undef MD_CHK + +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} + +/* + * Constant-flow memcpy from variable position in buffer. + * - functionally equivalent to memcpy(dst, src + offset_secret, len) + * - but with execution flow independent from the value of offset_secret. + */ +void mbedtls_ssl_cf_memcpy_offset( unsigned char *dst, + const unsigned char *src_base, + size_t offset_secret, + size_t offset_min, size_t offset_max, + size_t len ) +{ + size_t offset; + + for( offset = offset_min; offset <= offset_max; offset++ ) + { + mbedtls_ssl_cf_memcpy_if_eq( dst, src_base + offset, len, + offset, offset_secret ); + } +} +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +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_SSL_SOME_SUITES_USE_CBC) + 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; + + /* + * 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 &= ( padlen <= ssl->in_msglen ); + correct &= ( padding_idx <= MBEDTLS_SSL_MAX_CONTENT_LEN + + ssl->transform_in->maclen ); + + padding_idx *= correct; + + for( i = 0; 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_SSL_SOME_SUITES_USE_CBC) */ + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "raw buffer after decryption", + ssl->in_msg, ssl->in_msglen ); +#endif + + /* + * 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]; + unsigned char mac_peer[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 ); + memcpy( mac_peer, ssl->in_msg + ssl->in_msglen, + ssl->transform_in->maclen ); + } + 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 ) + { + int ret; + unsigned char add_data[13]; + + /* + * The next two sizes are the minimum and maximum values of + * in_msglen over all padlen values. + * + * They're independent of padlen, since we previously did + * in_msglen -= padlen. + * + * Note that max_len + maclen is never more than the buffer + * length, as we previously did in_msglen -= maclen too. + */ + const size_t max_len = ssl->in_msglen + padlen; + const size_t min_len = ( max_len > 256 ) ? max_len - 256 : 0; + + memcpy( add_data + 0, ssl->in_ctr, 8 ); + memcpy( add_data + 8, ssl->in_hdr, 3 ); + memcpy( add_data + 11, ssl->in_len, 2 ); + + ret = mbedtls_ssl_cf_hmac( &ssl->transform_in->md_ctx_dec, + add_data, sizeof( add_data ), + ssl->in_msg, ssl->in_msglen, + min_len, max_len, + mac_expect ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_cf_hmac", ret ); + return( ret ); + } + + mbedtls_ssl_cf_memcpy_offset( mac_peer, ssl->in_msg, + ssl->in_msglen, + min_len, max_len, + ssl->transform_in->maclen ); + } + 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 ); + } + +#if defined(MBEDTLS_SSL_DEBUG_ALL) + MBEDTLS_SSL_DEBUG_BUF( 4, "expected mac", mac_expect, ssl->transform_in->maclen ); + MBEDTLS_SSL_DEBUG_BUF( 4, "message mac", mac_peer, ssl->transform_in->maclen ); +#endif + + if( mbedtls_ssl_safer_memcmp( mac_peer, 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 ) + { +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 + && ssl->in_msgtype != MBEDTLS_SSL_MSG_APPLICATION_DATA ) + { + /* TLS v1.2 explicitly disallows zero-length messages which are not application data */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid zero-length message type: %d", ssl->in_msgtype ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } +#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ + + 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; + ptrdiff_t bytes_written = ssl->out_msg - ssl->out_buf; + 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 - bytes_written; + + 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 - bytes_written; + + 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; + ptrdiff_t header_bytes = ssl->in_msg - ssl->in_buf; + 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_BUFFER_LEN - + header_bytes; + + 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_BUFFER_LEN - + ssl->transform_in->ctx_inflate.avail_out - header_bytes; + + 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 across 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 ); + + if ( (size_t)ret > len || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_recv returned %d bytes but only %lu were requested", + ret, (unsigned long)len ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + 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 ); + + if( (size_t)ret > ssl->out_left || ( INT_MAX > SIZE_MAX && ret > (int)SIZE_MAX ) ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "f_send returned %d bytes but only %lu bytes were sent", + ret, (unsigned long)ssl->out_left ) ); + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + } + + 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 int ssl_swap_epochs( mbedtls_ssl_context *ssl ) +{ + mbedtls_ssl_transform *tmp_transform; + unsigned char tmp_out_ctr[8]; +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) + int ret; +#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + + if( ssl->transform_out == ssl->handshake->alt_transform_out ) + { + MBEDTLS_SSL_DEBUG_MSG( 3, ( "skip swap epochs" ) ); + return( 0 ); + } + + 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 /* MBEDTLS_SSL_HW_RECORD_ACCEL */ + + return( 0 ); +} + +/* + * 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 ) +{ + int ret; + + 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; + if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) + return( ret ); + + ssl->handshake->retransmit_state = MBEDTLS_SSL_RETRANS_SENDING; + } + + while( ssl->handshake->cur_msg != NULL ) + { + 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 ) + { + if( ( ret = ssl_swap_epochs( ssl ) ) != 0 ) + return( ret ); + } + + 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_zeroize( 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; + + /* Use out_msg as temporary buffer for writing out HelloVerifyRequest, + * because the output buffer's already around. Don't use out_buf though, + * as we don't want to overwrite out_ctr. */ + 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_msg, 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 ) + { + int send_ret; + MBEDTLS_SSL_DEBUG_MSG( 1, ( "sending HelloVerifyRequest" ) ); + MBEDTLS_SSL_DEBUG_BUF( 4, "output record sent to network", + ssl->out_msg, len ); + /* 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. */ + send_ret = ssl->f_send( ssl->p_bio, ssl->out_msg, len ); + MBEDTLS_SSL_DEBUG_RET( 2, "ssl->f_send", send_ret ); + (void) send_ret; + + return( MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ); + } + + if( ret == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "cookie is valid, resetting 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 ); + } + + /* + * DTLS-related tests. + * Check epoch before checking length constraint because + * the latter varies with the epoch. E.g., if a ChangeCipherSpec + * message gets duplicated before the corresponding Finished message, + * the second ChangeCipherSpec should be discarded because it belongs + * to an old epoch, but not because its length is shorter than + * the minimum record length for packets using the new record transform. + * Note that these two kinds of failures are handled differently, + * as an unexpected record is silently skipped but an invalid + * record leads to the entire datagram being dropped. + */ +#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]; + + /* 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 + + /* 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 ); + } + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + + /* 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 + } + + 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 ) + { + if( ssl->in_msglen != 2 ) + { + /* Note: Standard allows for more than one 2 byte alert + to be packed in a single message, but Mbed TLS doesn't + currently support this. */ + MBEDTLS_SSL_DEBUG_MSG( 1, ( "invalid alert message, len: %d", + ssl->in_msglen ) ); + return( MBEDTLS_ERR_SSL_INVALID_RECORD ); + } + + 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 ( i + 3 > 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 ); + } + 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) + +typedef int (*finish_sha384_t)(mbedtls_sha512_context*, unsigned char*); + +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]; + /* + * For SHA-384, we can save 16 bytes by keeping padbuf 48 bytes long. + * However, to avoid stringop-overflow warning in gcc, we have to cast + * mbedtls_sha512_finish_ret(). + */ + finish_sha384_t finish_sha384 = (finish_sha384_t)mbedtls_sha512_finish_ret; + + 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"; + + finish_sha384( &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 + */ + ssl->in_buf = NULL; + ssl->out_buf = NULL; + 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 ) ); + ret = MBEDTLS_ERR_SSL_ALLOC_FAILED; + goto error; + } + +#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 ) + goto error; + + return( 0 ); + +error: + mbedtls_free( ssl->in_buf ); + mbedtls_free( ssl->out_buf ); + + ssl->conf = NULL; + + ssl->in_buf = NULL; + ssl->out_buf = NULL; + + ssl->in_hdr = NULL; + ssl->in_ctr = NULL; + ssl->in_len = NULL; + ssl->in_iv = NULL; + ssl->in_msg = NULL; + + ssl->out_hdr = NULL; + ssl->out_ctr = NULL; + ssl->out_len = NULL; + ssl->out_iv = NULL; + ssl->out_msg = NULL; + + return( ret ); +} + +/* + * 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; + + ssl->session_in = NULL; + ssl->session_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_cert; + + new_cert = mbedtls_calloc( 1, sizeof( mbedtls_ssl_key_cert ) ); + if( new_cert == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + new_cert->cert = cert; + new_cert->key = key; + new_cert->next = NULL; + + /* Update head is the list was null, else add to the end */ + if( *head == NULL ) + { + *head = new_cert; + } + else + { + mbedtls_ssl_key_cert *cur = *head; + while( cur->next != NULL ) + cur = cur->next; + cur->next = new_cert; + } + + 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 > MBEDTLS_SSL_MAX_ALPN_NAME_LEN ) || + ( tot_len > MBEDTLS_SSL_MAX_ALPN_LIST_LEN ) ) + 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 = 0; + const mbedtls_ssl_transform *transform = ssl->transform_out; + unsigned block_size; + + if( transform == NULL ) + return( (int) mbedtls_ssl_hdr_len( ssl ) ); + +#if defined(MBEDTLS_ZLIB_SUPPORT) + if( ssl->session_out->compression != MBEDTLS_SSL_COMPRESS_NULL ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + + 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: + + block_size = mbedtls_cipher_get_block_size( + &transform->cipher_ctx_enc ); + + /* Expansion due to the addition of the MAC. */ + transform_expansion += transform->maclen; + + /* Expansion due to the addition of CBC padding; + * Theoretically up to 256 bytes, but we never use + * more than the block size of the underlying cipher. */ + transform_expansion += block_size; + + /* For TLS 1.1 or higher, an explicit IV is added + * after the record header. */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2) + if( ssl->minor_ver >= MBEDTLS_SSL_MINOR_VERSION_2 ) + transform_expansion += block_size; +#endif /* MBEDTLS_SSL_PROTO_TLS1_1 || MBEDTLS_SSL_PROTO_TLS1_2 */ + + 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 ); + } + } + + 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; + + /* Zeroising the plaintext buffer to erase unused application data + from the memory. */ + mbedtls_zeroize( ssl->in_offt, 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. + * + * According to RFC 5246 Section 6.2.1: + * + * Zero-length fragments of Application data MAY be sent as they are + * potentially useful as a traffic analysis countermeasure. + * + * Therefore, it is possible that the input message length is 0 and the + * corresponding return code is 0 on success. + */ +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 ) + { + /* + * The user has previously tried to send the data and + * MBEDTLS_ERR_SSL_WANT_WRITE or the message was only partially + * written. In this case, we expect the high-level write function + * (e.g. mbedtls_ssl_write()) to be called with the same parameters + */ + if( ( ret = mbedtls_ssl_flush_output( ssl ) ) != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_flush_output", ret ); + return( ret ); + } + } + else + { + /* + * The user is trying to send a message the first time, so we need to + * copy the data into the internal buffers and setup the data structure + * to keep track of partial writes + */ + 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[] = { +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + MBEDTLS_ECP_DP_SECP256R1, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + MBEDTLS_ECP_DP_SECP384R1, +#endif + 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 */ diff --git a/third-party/mbedtls-3.6/library/threading.c b/third-party/mbedtls-3.6/library/threading.c new file mode 100644 index 00000000..df16fe72 --- /dev/null +++ b/third-party/mbedtls-3.6/library/threading.c @@ -0,0 +1,180 @@ +/* + * Threading abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + /* A nonzero value of is_valid indicates a successfully initialized + * mutex. This is a workaround for not being able to return an error + * code for this function. The lock/unlock functions return an error + * if is_valid is nonzero. The Mbed TLS unit test code uses this field + * to distinguish more states of the mutex; see helpers.function for + * details. */ + 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; + +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) + mbedtls_mutex_init( &mbedtls_threading_gmtime_mutex ); +#endif +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) + mbedtls_mutex_free( &mbedtls_threading_gmtime_mutex ); +#endif +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +#if defined(MBEDTLS_FS_IO) +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT; +#endif + +#endif /* MBEDTLS_THREADING_C */ diff --git a/third-party/mbedtls-3.6/library/timing.c b/third-party/mbedtls-3.6/library/timing.c new file mode 100644 index 00000000..6b91ea43 --- /dev/null +++ b/third-party/mbedtls-3.6/library/timing.c @@ -0,0 +1,560 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#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 void TimerProc( void *TimerContext ) +{ + (void) TimerContext; + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + /* _endthread will be called implicitly on return + * That ensures execution of thread funcition's epilogue */ +} + +void mbedtls_set_alarm( int seconds ) +{ + 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; + (void) _beginthread( TimerProc, 0, NULL ); +} + +#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 */ diff --git a/third-party/mbedtls-3.6/library/version.c b/third-party/mbedtls-3.6/library/version.c new file mode 100644 index 00000000..22682b85 --- /dev/null +++ b/third-party/mbedtls-3.6/library/version.c @@ -0,0 +1,75 @@ +/* + * Version information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" +#include + +unsigned int mbedtls_version_get_number() +{ + 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 */ diff --git a/third-party/mbedtls-3.6/library/version_features.c b/third-party/mbedtls-3.6/library/version_features.c new file mode 100644 index 00000000..ee13f789 --- /dev/null +++ b/third-party/mbedtls-3.6/library/version_features.c @@ -0,0 +1,759 @@ +/* + * Version feature information + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_VERSION_C) + +#include "mbedtls/version.h" + +#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_CONSTANT_FLOW_MEMSAN) + "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */ +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) + "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND", +#endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */ +#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_REMOVE_3DES_CIPHERSUITES) + "MBEDTLS_REMOVE_3DES_CIPHERSUITES", +#endif /* MBEDTLS_REMOVE_3DES_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_ECP_NO_INTERNAL_RNG) + "MBEDTLS_ECP_NO_INTERNAL_RNG", +#endif /* MBEDTLS_ECP_NO_INTERNAL_RNG */ +#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_TEST_HOOKS) + "MBEDTLS_TEST_HOOKS", +#endif /* MBEDTLS_TEST_HOOKS */ +#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 */ diff --git a/third-party/mbedtls-3.6/library/x509.c b/third-party/mbedtls-3.6/library/x509.c new file mode 100644 index 00000000..377c106d --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509.c @@ -0,0 +1,1121 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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) +#include "mbedtls/platform_time.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#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) parameters + */ +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 ); + + end = *p + len; + + 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; + + if( *p != end ) + { + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + 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; + + /* Extension structure use EXPLICIT tagging. That is, the actual + * `Extensions` structure is wrapped by a tag-length pair using + * the respective context-specific tag. */ + ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + 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) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/certs.h" + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &cacert ); + 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" ); + + goto cleanup; + } + + 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" ); + + goto cleanup; + } + + 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" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + +cleanup: + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); +#else + ((void) verbose); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA256_C */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ diff --git a/third-party/mbedtls-3.6/library/x509_create.c b/third-party/mbedtls-3.6/library/x509_create.c new file mode 100644 index 00000000..252e835b --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509_create.c @@ -0,0 +1,365 @@ +/* + * X.509 base functions for creating certificates / CSRs + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CREATE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" + +#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 */ diff --git a/third-party/mbedtls-3.6/library/x509_crl.c b/third-party/mbedtls-3.6/library/x509_crl.c new file mode 100644 index 00000000..73a300d2 --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509_crl.c @@ -0,0 +1,801 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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; + + if( *p == end ) + return( 0 ); + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + return( ret ); + + end = ext->p + ext->len; + + 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; + + cur_entry->raw.tag = **p; + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + 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 */ diff --git a/third-party/mbedtls-3.6/library/x509_crt.c b/third-party/mbedtls-3.6/library/x509_crt.c new file mode 100644 index 00000000..124f3dde --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509_crt.c @@ -0,0 +1,2506 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + + 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( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + + 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( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + + 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( MBEDTLS_ERR_X509_INVALID_FORMAT + 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( MBEDTLS_ERR_X509_INVALID_FORMAT + 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 ); + + /* Do not accept max_pathlen equal to INT_MAX to avoid a signed integer + * overflow, which is an undefined behavior. */ + if( *max_pathlen == INT_MAX ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + (*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( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + return( ret ); + + end = crt->v3_ext.p + crt->v3_ext.len; + 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 */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.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 ); + + 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.tag != sig_params2.tag || + 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 ); +} + +/* + * 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 ); +} + +/* + * 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 ) + { + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if 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 || + x509_name_cmp( &crl_list->issuer, &ca->subject ) != 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( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + 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 */ + +/* + * 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 ); +} + +/* + * Verify a certificate with no parent inside the chain + * (either the parent is a trusted root, or there is no parent) + * + * See comments for mbedtls_x509_crt_verify_with_profile() + * (also for notation used below) + * + * This function is called in two cases: + * - child was found to have a parent in trusted roots, in which case we're + * called with trust_ca pointing directly to that parent (not the full list) + * - this is cases 1, 2 and 3 of the comment on verify_with_profile() + * - case 1 is special as child and trust_ca point to copies of the same + * certificate then + * - child was found to have no parent either in the chain or in trusted CAs + * - this is cases 4 and 5 of the comment on verify_with_profile() + * + * For historical reasons, the function currently does not assume that + * trust_ca points directly to the right root in the first case, and it + * doesn't know in which case it starts, so it always starts by searching for + * a parent in trust_ca. + */ +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( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + /* Cannot check signature, no need to try any CA */ + trust_ca = NULL; + } + + 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->subject_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->subject_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 ); +} + +/* + * Verify a certificate with a parent inside the chain + * + * See comments for mbedtls_x509_crt_verify_with_profile() + */ +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( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + } + else + { + 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 + * + * The chain building/verification is spread accross 4 functions: + * - this one + * - x509_crt_verify_child() + * - x509_crt_verify_top() + * - x509_crt_check_parent() + * + * There are five main cases to consider. Let's introduce some notation: + * - E means the end-entity certificate + * - I an intermediate CA + * - R the trusted root CA this chain anchors to + * - T the list of trusted roots (R and possible some others) + * + * The main cases with the calling sequence of the crt_verify_xxx() are: + * 1. E = R (explicitly trusted EE cert) + * verify(E, T) -> verify_top(E, R) + * 2. E -> R (EE signed by trusted root) + * verify(E, T) -> verify_top(E, R) + * 3. E -> I -> R (EE signed by intermediate signed by trusted root) + * verify(E, T) -> verify_child(E, I, T) -> verify_top(I, R) + * (plus variant with multiple intermediates) + * 4. E -> I (EE signed by intermediate that's not trusted) + * verify(E, T) -> verify_child(E, I, T) -> verify_top(I, T) + * (plus variant with multiple intermediates) + * 5. E (EE not trusted) + * verify(E, T) -> verify_top(E, T) + * + * Note: this notation and case numbering is also used in x509_crt_verify_top() + */ +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 */ diff --git a/third-party/mbedtls-3.6/library/x509_csr.c b/third-party/mbedtls-3.6/library/x509_csr.c new file mode 100644 index 00000000..50988e01 --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509_csr.c @@ -0,0 +1,448 @@ +/* + * X.509 Certificate Signing Request (CSR) parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( buf[buflen - 1] == '\0' ) + { + mbedtls_pem_init( &pem ); + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE REQUEST-----", + "-----END CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + if( ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN NEW CERTIFICATE REQUEST-----", + "-----END NEW CERTIFICATE REQUEST-----", + buf, NULL, 0, &use_len ); + } + + if( ret == 0 ) + { + /* + * Was PEM encoded, parse the result + */ + ret = mbedtls_x509_csr_parse_der( csr, pem.buf, pem.buflen ); + } + + mbedtls_pem_free( &pem ); + if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + } +#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 */ diff --git a/third-party/mbedtls-3.6/library/x509write_crt.c b/third-party/mbedtls-3.6/library/x509write_crt.c new file mode 100644 index 00000000..daebb813 --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509write_crt.c @@ -0,0 +1,551 @@ +/* + * X.509 certificate writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/sha1.h" + +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif /* MBEDTLS_PEM_WRITE_C */ + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * For the currently used signature algorithms the buffer to store any signature + * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) + */ +#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE +#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#else +#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +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 */ + +static size_t crt_get_unused_bits_for_named_bitstring( unsigned char bitstring, + size_t bit_offset ) +{ + size_t unused_bits; + + /* Count the unused bits removing trailing 0s */ + for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) + if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) + break; + + return( unused_bits ); +} + +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; + size_t unused_bits; + const unsigned int allowed_bits = MBEDTLS_X509_KU_DIGITAL_SIGNATURE | + MBEDTLS_X509_KU_NON_REPUDIATION | + MBEDTLS_X509_KU_KEY_ENCIPHERMENT | + MBEDTLS_X509_KU_DATA_ENCIPHERMENT | + MBEDTLS_X509_KU_KEY_AGREEMENT | + MBEDTLS_X509_KU_KEY_CERT_SIGN | + MBEDTLS_X509_KU_CRL_SIGN; + + /* Check that nothing other than the allowed flags is set */ + if( ( key_usage & ~allowed_bits ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + + c = buf + 4; + ku = (unsigned char)key_usage; + unused_bits = crt_get_unused_bits_for_named_bitstring( ku, 1 ); + ret = mbedtls_asn1_write_bitstring( &c, buf, &ku, 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + 1, c, (size_t)ret ); + 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; + size_t unused_bits; + int ret; + + c = buf + 4; + + unused_bits = crt_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, + buf, + &ns_cert_type, + 8 - unused_bits ); + if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_crt_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + 0, c, (size_t)ret ); + 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[SIGNATURE_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 */ diff --git a/third-party/mbedtls-3.6/library/x509write_csr.c b/third-party/mbedtls-3.6/library/x509write_csr.c new file mode 100644 index 00000000..cbf4276e --- /dev/null +++ b/third-party/mbedtls-3.6/library/x509write_csr.c @@ -0,0 +1,331 @@ +/* + * X.509 Certificate Signing Request writing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ +/* + * References: + * - CSRs: PKCS#10 v1.7 aka RFC 2986 + * - attributes: PKCS#9 v2.0 aka RFC 2985 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) + +#include "mbedtls/x509_csr.h" +#include "mbedtls/oid.h" +#include "mbedtls/asn1write.h" + +#include +#include + +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * For the currently used signature algorithms the buffer to store any signature + * must be at least of size MAX(MBEDTLS_ECDSA_MAX_LEN, MBEDTLS_MPI_MAX_SIZE) + */ +#if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE +#define SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#else +#define SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif + +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 ); +} + +static size_t csr_get_unused_bits_for_named_bitstring( unsigned char bitstring, + size_t bit_offset ) +{ + size_t unused_bits; + + /* Count the unused bits removing trailing 0s */ + for( unused_bits = bit_offset; unused_bits < 8; unused_bits++ ) + if( ( ( bitstring >> unused_bits ) & 0x1 ) != 0 ) + break; + + return( unused_bits ); +} + +int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage ) +{ + unsigned char buf[4]; + unsigned char *c; + size_t unused_bits; + int ret; + + c = buf + 4; + + unused_bits = csr_get_unused_bits_for_named_bitstring( key_usage, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, buf, &key_usage, 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ), + c, (size_t)ret ); + 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; + size_t unused_bits; + int ret; + + c = buf + 4; + + unused_bits = csr_get_unused_bits_for_named_bitstring( ns_cert_type, 0 ); + ret = mbedtls_asn1_write_bitstring( &c, + buf, + &ns_cert_type, + 8 - unused_bits ); + + if( ret < 0 ) + return( ret ); + else if( ret < 3 || ret > 4 ) + return( ret ); + + ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE, + MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ), + c, (size_t)ret ); + 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[SIGNATURE_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 + */ + ret = mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash ); + if( ret != 0 ) + return( ret ); + + 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 */ diff --git a/third-party/mbedtls-3.6/library/xtea.c b/third-party/mbedtls-3.6/library/xtea.c new file mode 100644 index 00000000..a1e51414 --- /dev/null +++ b/third-party/mbedtls-3.6/library/xtea.c @@ -0,0 +1,306 @@ +/* + * An 32-bit implementation of the XTEA algorithm + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later + * + * This file is provided under the Apache License 2.0, or the + * GNU General Public License v2.0 or later. + * + * ********** + * Apache License 2.0: + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ********** + * + * ********** + * GNU General Public License v2.0 or later: + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * ********** + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_XTEA_C) + +#include "mbedtls/xtea.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#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 */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = v; while( n-- ) *p++ = 0; +} + +/* + * 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 */ diff --git a/third-party/mbedtls-3.6/makefile b/third-party/mbedtls-3.6/makefile new file mode 100644 index 00000000..17f84019 --- /dev/null +++ b/third-party/mbedtls-3.6/makefile @@ -0,0 +1,5 @@ +include $(PROJECT_DIR)/sdkconfig + +include src.mk + +include $(SDK_DIR)/tools/build/compiler.mk \ No newline at end of file diff --git a/third-party/mbedtls-3.6/mbedtls.kconfig b/third-party/mbedtls-3.6/mbedtls.kconfig new file mode 100644 index 00000000..b832fe10 --- /dev/null +++ b/third-party/mbedtls-3.6/mbedtls.kconfig @@ -0,0 +1,3 @@ +menu "MBEDTLS Freertos Port Configuration" + +endmenu \ No newline at end of file diff --git a/third-party/mbedtls-3.6/mbedtls_freertos.mk b/third-party/mbedtls-3.6/mbedtls_freertos.mk new file mode 100644 index 00000000..8e1cddb9 --- /dev/null +++ b/third-party/mbedtls-3.6/mbedtls_freertos.mk @@ -0,0 +1,8 @@ +MBEDTLS_FREERTOS_CUR_DIR := $(FREERTOS_SDK_DIR)/third-party + +ifdef CONFIG_USE_MBEDTLS + +INC_DIR += $(MBEDTLS_FREERTOS_CUR_DIR)/mbedtls-3.6 +SRC_DIR += $(MBEDTLS_FREERTOS_CUR_DIR)/mbedtls-3.6 + +endif diff --git a/third-party/mbedtls-3.6/ports/inc/tls_certificate.h b/third-party/mbedtls-3.6/ports/inc/tls_certificate.h new file mode 100644 index 00000000..a4e5a48e --- /dev/null +++ b/third-party/mbedtls-3.6/ports/inc/tls_certificate.h @@ -0,0 +1,28 @@ +/* + * 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_CERTIFICATE_H + #define MBEDTLS_CERTIFICATE_H + + +extern const char mbedtls_root_certificate[]; + +extern const size_t mbedtls_root_certificate_len; + +#endif diff --git a/third-party/mbedtls-3.6/ports/inc/tls_net.h b/third-party/mbedtls-3.6/ports/inc/tls_net.h new file mode 100644 index 00000000..3d60cd9d --- /dev/null +++ b/third-party/mbedtls-3.6/ports/inc/tls_net.h @@ -0,0 +1,224 @@ +/** + * \file net.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_H +#define MBEDTLS_NET_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/ssl.h" + +#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.h */ diff --git a/third-party/mbedtls-3.6/ports/src/tls_certificate.c b/third-party/mbedtls-3.6/ports/src/tls_certificate.c new file mode 100644 index 00000000..6b78d3d8 --- /dev/null +++ b/third-party/mbedtls-3.6/ports/src/tls_certificate.c @@ -0,0 +1,47 @@ + +/* + * Copyright (c) 2006-2018 RT-Thread Development Team. All rights reserved. + * License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * 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 "mbedtls/certs.h" + +const char mbedtls_root_certificate[] = +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\r\n" \ +"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\r\n" \ +"DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\r\n" \ +"PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\r\n" \ +"Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\r\n" \ +"AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\r\n" \ +"rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\r\n" \ +"OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\r\n" \ +"xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\r\n" \ +"7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\r\n" \ +"aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\r\n" \ +"HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\r\n" \ +"SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\r\n" \ +"ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\r\n" \ +"AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\r\n" \ +"R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\r\n" \ +"JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\r\n" \ +"Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\r\n" \ +"-----END CERTIFICATE-----\r\n" \ + +; + +const size_t mbedtls_root_certificate_len = sizeof(mbedtls_root_certificate); + diff --git a/third-party/mbedtls-3.6/ports/src/tls_net.c b/third-party/mbedtls-3.6/ports/src/tls_net.c new file mode 100644 index 00000000..72fbc0f9 --- /dev/null +++ b/third-party/mbedtls-3.6/ports/src/tls_net.c @@ -0,0 +1,508 @@ +/* + * 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) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* Some MS functions want int and MSVC warns if we pass size_t, + * but the standard fucntions 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 +#include +#include + +/* 头文件包含 */ +#include +#include +#include +#include +#include +#include + +#include "lwip/dhcp.h" +#include "lwip/tcpip.h" +#include "lwip/netdb.h" +#include "lwip/sockets.h" +#include "netif/ethernet.h" + +#include "tls_net.h" + +/* + * Prepare for using the sockets interface + */ +static int net_prepare( void ) +{ + 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 ) + { + printf("socket error\n"); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 ) + { + ret = 0; + break; + } + + closesocket( 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 ) + { + closesocket( ctx->fd ); + ret = MBEDTLS_ERR_NET_SOCKET_FAILED; + continue; + } + + if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 ) + { + closesocket( 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 ) + { + closesocket( ctx->fd ); + ret = MBEDTLS_ERR_NET_LISTEN_FAILED; + continue; + } + } + + /* I we ever get there, it's a success */ + 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 ) +{ + /* + * Never return 'WOULD BLOCK' on a non-blocking socket + */ + if( ( fcntl( ctx->fd, F_GETFL, 0) & O_NONBLOCK ) != O_NONBLOCK ) + return( 0 ); + return( 1 ); + +} +#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_in 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 + socklen_t n = (int) sizeof( client_addr ); + socklen_t 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_in 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_in ); + + if( getsockname( client_ctx->fd, + (struct sockaddr *) &local_addr, &n ) != 0 || + ( bind_ctx->fd = (int) socket( local_addr.sin_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.sin_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 + { + + } + } + + return( 0 ); +} + +/* + * Set the socket blocking or non-blocking + */ +int net_set_block(int fd) +{ +#if defined(WIN32) || defined(_WIN32_WCE) + long n = 0; + return (ioctlsocket(fd, FIONBIO, &n)); +#else + return (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK)); +#endif +} + +int net_set_nonblock(int fd) +{ +#if defined(WIN32) || defined(_WIN32_WCE) + long n = 1; + return (ioctlsocket(fd, FIONBIO, &n)); +#else + return (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | 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) recv( fd, buf, len, 0); + + + 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) send( fd, buf, len, 0 ); + + 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; + + closesocket( ctx->fd ); + ctx->fd = -1; +} + + diff --git a/third-party/mbedtls-3.6/src.mk b/third-party/mbedtls-3.6/src.mk new file mode 100644 index 00000000..58722910 --- /dev/null +++ b/third-party/mbedtls-3.6/src.mk @@ -0,0 +1,11 @@ + +ifdef CONFIG_USE_MBEDTLS + +MBEDTLS_RT_C_DIR = $(abspath $(FREERTOS_SDK_DIR)/third-party/mbedtls-3.6) + +# src code of lwip +ABSOLUTE_CFILES += $(wildcard $(MBEDTLS_RT_C_DIR)/library/*.c) \ + $(wildcard $(MBEDTLS_RT_C_DIR)/ports/src/*.c) + +endif #CONFIG_USE_MBEDTLS + diff --git a/third-party/third-party.kconfig b/third-party/third-party.kconfig index cf55b0cc..d6f25c50 100644 --- a/third-party/third-party.kconfig +++ b/third-party/third-party.kconfig @@ -11,6 +11,17 @@ config USE_LWIP source "$(FREERTOS_SDK_DIR)/third-party/lwip-2.1.2/lwip.kconfig" endif +config USE_MBEDTLS + bool + prompt "Use mbedtls" + default n + help + Include MBEDTLS for Network Protocol + + if USE_MBEDTLS + source "$(FREERTOS_SDK_DIR)/third-party/mbedtls-3.6/mbedtls.kconfig" + endif + config USE_LETTER_SHELL bool prompt "Use letter shell" diff --git a/third-party/thirdparty.mk b/third-party/thirdparty.mk index e4b0b679..d94e4b51 100644 --- a/third-party/thirdparty.mk +++ b/third-party/thirdparty.mk @@ -66,6 +66,17 @@ lib_lwip_info: BAREMETAL_LIBS+= $(BUILD_OUT_PATH)/lib_lwip.a endif +ifdef CONFIG_USE_MBEDTLS +$(BUILD_OUT_PATH)/lib_mbedtls.a: lib_mbedtls.a +lib_mbedtls.a: + $(call rtos_invoke_make_in_dir,$(FREERTOS_SDK_DIR),third-party/mbedtls-3.6,makefile,all,) +lib_mbedtls_debug: + $(call rtos_invoke_make_in_dir,$(FREERTOS_SDK_DIR),third-party/mbedtls-3.6,makefile,debug,) +lib_mbedtls_info: + $(call rtos_invoke_make_in_dir,$(FREERTOS_SDK_DIR),third-party/mbedtls-3.6,makefile,compiler_info,) +BAREMETAL_LIBS+= $(BUILD_OUT_PATH)/lib_mbedtls.a +endif + ifdef CONFIG_USE_SFUD $(BUILD_OUT_PATH)/lib_sfud.a: lib_sfud.a lib_sfud.a: -- Gitee

%i$lW}xSjzNI9e_r{(YsG6d94e%RD$S%ZoMr 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 diff --git a/example/system/amp/openamp/driver_core/fig/20231017165755.png b/example/system/amp/openamp/driver_core/fig/Test32_Results.png similarity index 100% rename from example/system/amp/openamp/driver_core/fig/20231017165755.png rename to example/system/amp/openamp/driver_core/fig/Test32_Results.png diff --git a/example/system/amp/openamp/driver_core/fig/20231017160632.png b/example/system/amp/openamp/driver_core/fig/Test64_Results.png similarity index 100% rename from example/system/amp/openamp/driver_core/fig/20231017160632.png rename to example/system/amp/openamp/driver_core/fig/Test64_Results.png diff --git a/example/system/amp/openamp/driver_core/fig/e2000_aarch32_openamp_startup.png b/example/system/amp/openamp/driver_core/fig/e2000_aarch32_openamp_startup.png index 4f50f3d124425b8371e2229b0ea639bc1393d504..264403e640fbe7fff78052ebd515118fa0eb796e 100644 GIT binary patch literal 133687 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 C20N7i literal 251503 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